2016-01-22 9 views
6

Gibt es eine Möglichkeit, einer Klasseninstanz Eigenschaftenwerte zuzuweisen, auch wenn es sich nicht um einen Parameter im init-Konstruktor handelt? Zum Beispiel in C# kann ich dies tun:Ein-Schritt-Objekt-Erstellung und Eigenschaftsinitialisierung in Swift?

public class Student 
{ 
    public string firstName; 
    public string lastName; 
} 

var student1 = new Student(); 
var student2 = new Student { firstName = "John", lastName = "Doe" }; 

Hinweis für student2 ich noch Werte bei der Initialisierung zugewiesen werden kann, auch wenn es in der Klasse kein Konstruktor ist.

Ich konnte nicht in der documentation finden, wenn Sie so etwas für Swift tun können. Wenn nicht, gibt es eine Möglichkeit, extensions zu verwenden, um die Student Klasse zu erweitern, um Eigenschaftswerte während der Initialisierung zuzuweisen?

Der Grund, warum ich für diese Suche ist, so kann ich ohne explizit Variablen für jeden Schüler Instanz, wie dies eine Reihe von Fällen zu einem Array hinzuzufügen:

var list = new[] { 
    new Student { firstName = "John", lastName = "Doe" }, 
    new Student { firstName = "Jane", lastName = "Jones" }, 
    new Student { firstName = "Jason", lastName = "Smith" } 
} 

Jede native oder elegante Art und Weise zu erreichen, das in Swift?

Antwort

8

Sie haben ein paar Optionen, je nachdem, wie Sie wollen um diesen Typ zu konfigurieren und welche Syntax für Sie am bequemsten ist.

Sie könnten einen praktischen Initialisierer definieren, der die Eigenschaften akzeptiert, die Sie festlegen möchten. Nützlich, wenn Sie immer die gleichen Eigenschaften festlegen, weniger nützlich, wenn Sie einen inkonsistenten Satz optionaler Eigenschaften festlegen.

public class Student 
{ 
    public var firstName:String?; 
    public var lastName:String?; 
} 

extension Student { 
    convenience init(firstName: String, lastName: String) { 
     self.init() 
     self.firstName = firstName 
     self.lastName = lastName 
    } 
} 

Student(firstName: "Any", lastName: "Body") 

Sie könnten einen Convenience-Initialisierer definieren, der einen Block zur Konfiguration der neuen Instanz akzeptiert.

extension Student { 
    convenience init(_ configure: (Student) -> Void) { 
     self.init() 
     configure(self) 
    } 
} 

Student({ $0.firstName = "Any"; $0.lastName = "Body" }) 

Sie könnten tap Methode als Erweiterung Rubys imitieren, so dass Sie auf ein Objekt in der Mitte eines Verfahrens Kette arbeiten kann.

extension Student { 
    func tap(block: (Student) -> Void) -> Self { 
     block(self) 
     return self 
    } 
} 

Student().tap({ $0.firstName = "Any"; $0.lastName = "body"}) 

Wenn das letzte ist nützlich Sie ein beliebiges Objekt zu übernehmen tap auf vielleicht wollen in der Lage sein. Ich glaube nicht, dass Sie automatisch tun können, aber Sie können eine Standard-Implementierung definieren, um es einfacher zu machen:

protocol Tap: AnyObject {} 

extension Tap { 
    func tap(block: (Self) -> Void) -> Self { 
     block(self) 
     return self 
    } 
} 

extension Student: Tap {} 

Student().tap({ $0.firstName = "Any"; $0.lastName = "body"}) 
+0

Das ist brillant! – TruMan1

4

Wenn Ihre Klasse keine erforderliche initialiser hat, können Sie eine Schließung Methode verwenden, um die Studenten Eigenschaften einzustellen, bevor das neue Studenten Objekt wie folgt Rückkehr:

public class Student { 
    var firstName = String() 
    var lastName = String() 
} 

let student1 = Student() 
let student2: Student = { 
    let student = Student() 
    student.firstName = "John" 
    student.lastName = "Doe" 
    return student 
}() 

print(student2.firstName) // John 
print(student2.lastName) // Doe 
1

Der Grund, warum ich für diese Suche ist, so kann ich eine Reihe von Instanzen eines hinzufügen [.] Array, ohne explizit Variablen für jeden Schüler Instanz

ich bin nicht vertraut mit C#, aber in Swift zu erstellen, können Sie das nur tun, indem Sie die Objekte in der Array-Deklaration zu initialisieren:

var list: [Student] = [ 
    Student(firstName: "John", lastName: "Doe"), 
    Student(firstName: "Jane", lastName: "Jones"), 
    Student(firstName: "Jason", lastName: "Smith") 
] 

Die anderen vorgeschlagenen Methoden sind alle gleichermaßen gültig. Wenn Sie jedoch lediglich versuchen, ein Array zu befüllen, ohne Variablen zu deklarieren, macht Swift das einfach.

+1

Die Student-Klasse liegt außerhalb meiner Kontrolle und ich kann sie nicht bearbeiten. Es befindet sich in einem anderen Rahmen. Also kann ich es nur erben oder erweitern. – TruMan1

1

Ich wollte nur darauf hinweisen, dass, wenn Ihre Struktur unveränderlich sein kann, können Sie einfach lieber ein struct verwenden als ein class und Sie erhalten einen impliziten initializer kostenlos erhalten:

diese einfach in einen Spielplatz einfügen und ändere struct in class und du wirst sehen was ich meine.

struct Student 
{ 
    var firstName : String? 
    var lastName : String? 
} 

var student = Student(firstName: "Dan", lastName: "Beaulieu") 
+0

Ah hah das ist toll !! Habe nicht erkannt, dass Strukturen dies hatten, aber keine anderen Typen. Gut zu wissen!! Einzige Sache ist, dass die Student-Klasse außerhalb meiner Kontrolle in einer anderen Bibliothek vergraben ist, so dass ich ihre Quelle nicht ändern kann. – TruMan1

1

Diese nur syntaktische Süßigkeiten, aber ich benutze einen benutzerdefinierten Betreiber diese Art der Sache zu tun:

infix operator <- { associativity right precedence 90 } 
func <-<T:AnyObject>(var left:T, right:(T)->()) -> T 
{ 
    right(left) 
    return left 
} 

let rgbButtons:[UIButton] = 
    [ 
    UIButton() <- { $0.backgroundColor = UIColor.redColor() }, 
    UIButton() <- { $0.backgroundColor = UIColor.greenColor() }, 
    UIButton() <- { $0.backgroundColor = UIColor.blueColor() } 
    ]