2015-02-21 14 views
11

ich Swift bin neu und möchte ein Objekt der Membervariable mit einer Instanz Methode wie folgt initialisieren: in init MethodeAufruf Instanz-Methode bei der Initialisierung in Swift

class MyClass { 
    var x: String 
    var y: String 

    func createY() -> String { 
    self.y = self.x + "_test" // this computation could be much more complex 
    } 

    init(x: String) { 
    self.x = x 
    self.y = self.createY() 
    }  
} 

Grundsätzlich statt inlining all Initialisierungscode Ich möchte den Initialisierungscode y in eine dedizierte Methode createY extrahieren und diese Instanzmethode createY in aufrufen. Allerdings klagt Swift-Compiler (Swift 1.2 Compiler in Xcode 6.3 Beta):

Verwendung von 'Selbst' in 'xxx' Methodenaufruf vor super.init Selbst

Hier 'xxx' initialisieren ist die Name der Instanzmethode (createY).

Ich kann verstehen, was Swift Compiler beschweren und das potenzielle Problem, das es ansprechen möchte. Ich habe jedoch keine Ahnung, wie ich das beheben kann. Was sollte der korrekte Weg in Swift sein, um eine andere Instanz des Initialisierungscodes in init aufzurufen?

Derzeit verwende ich die folgenden Trick, wie Arbeit um, aber ich glaube nicht, das die idiomatische Lösung für dieses Problem ist (und diese Problemumgehung erfordert y deklariert werden mit var statt let, die mich auch ein ungutes Gefühl macht):

init(x: String) { 
    self.x = x 
    super.init() 
    self.y = createY() 
} 

Jeder Kommentar wird geschätzt. Vielen Dank.

Antwort

9

Konvertieren Sie createY() in eine globale oder Klassenfunktion, die x als Argument akzeptiert und eine y zurückgibt.

func createY(x: String) -> String { 
    return x + "_test" // this computation could be much more complex 
} 

Dann rufen Sie einfach normal von Ihrem init.

+0

Danke für die Antwort, es scheint, ich habe noch zu erklären ' y 'mit' var 'anstelle von' let ', auch wenn meine' y 'Variable unveränderlich ist? – nybon

+0

@nycon Ich habe den Code für die Klasse selbst hinzugefügt, um zu zeigen, wie ich 'createY()' gemeint habe. 'Let' sollte in Ordnung sein. –

1

Wie beantwortet here, erstellen Sie eine Klassenfunktion. Ich habe den vollständigen Code hinzugefügt.

class MyClass { 
    var x: String 
    var y: String 

    class func createY(x: String) -> String { 
     return x + "_test" // this computation could be much more complex 
    } 

    init(x: String) { 
     self.x = x 
     self.y = MyClass.createY(x) 
    }  
} 
1

ich denke, der Swift Weg, dies mit Computed Eigenschaften (https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html)

EDIT

Statt am Set zu ändern, um eine Funktion des Aufrufs eine Eigenschaft zu tun ist, /, können Sie verwenden berechnet Eigenschaften:

class MyClass { 

    var x: String? 
    var y: String? { 
     get { 
      return "\(x!)_test" 
     } 
    } 

    init(x: String!){ 
     self.x = x 
    } 
} 

let myClass = MyClass(x: "string") 
print(myClass.y!) #=> "string_test" 
+0

Sie können Ihre Antwort verbessern, indem Sie ein konkretes Beispiel angeben und nicht nur auf eine externe Seite verlinken (die möglicherweise verschwindet). – zeeMonkeez

+0

Entschuldigung, ich habe ein Beispiel hinzugefügt. – Struki84

+0

Wenn ich es richtig verstehe, berechnen berechnete Eigenschaften die Berechnung jedes Mal, wenn ich auf diese berechnete Eigenschaft zugreife, ist es korrekt? Wenn die Berechnung teuer ist und nur einmal während der Initialisierung benötigt wird, wie soll ich das machen? – nybon

0

In Swift 3, ich habe dieses Muster verwendet,

class MyClass { 
    var x: String? 
    private(set) lazy var y: String? = self.createY() 

    init(x: String){ self.x = x } 

    private func createY() -> String? 
    { 
    return "\(x ?? "nil") test" 
    } 
} 

Die geheime Sauce hier ist die Verwendung von private(set) lazy. Auf diese Weise können Sie Ihre Immobilie als var kennzeichnen. Und lazy wird die Initialisierung verzögern, bis Ihre init-Funktion abgeschlossen ist. Wenn Sie private(set) verwenden, können nur die Funktionen innerhalb dieser Klasse diese Eigenschaft einschließlich des Schlüsselworts lazy ändern, öffentliche Schnittstellen dürfen sie jedoch nicht ändern.Wenn Sie möchten, dass Ihre Schnittstelle Ihre Eigenschaft ändert, können Sie sie natürlich auch als internal (Standard) oder public markieren. Aber Sie müssen lassen Sie es ein lazy var

markiert
0

Sie in diesem Ansatz können

Klasse MyClass: NSObject {

 let x: String 
     var y: String 

     init(x: String) { 

      self.x = x 
      self.y = self.x + "_test" 
      print(self.x) 
      print(self.y) 
     } 
} 
+0

Danke für die Antwort, aber wie ich oben erwähnt habe, möchte ich nicht "den ganzen Initialisierungscode in der Init-Methode einbinden". – nybon

0
class MyClass { 
     let x: String 
     lazy var y : String = { 
       return x + "_test" 
      }() 
     init(x: String) { 
      self.x = x 
     } 
} 
+1

Nicht wirklich hilfreich ohne weitere Erläuterungen ;-( – GhostCat

Verwandte Themen