2016-01-22 90 views
6

Czy istnieje sposób na przypisanie wartości właściwości do instancji klasy, nawet jeśli nie jest to parametr w konstruktorze init? Na przykład, w języku C# można to zrobić:Jednoetapowe tworzenie obiektu i inicjowanie właściwości w Swift?

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

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

Wskazówki dla student2 nadal mogę przypisać wartości podczas inicjalizacji, mimo że nie ma konstruktor w klasie.

Nie mogłem znaleźć w documentation, jeśli możesz zrobić coś takiego dla Swift. Jeśli nie, czy istnieje sposób użycia extensions do rozszerzenia klasy Student w celu przypisania wartości właściwości podczas inicjowania?

Powodem szukam jest to więc mogę dodać kilka wystąpień do tablicy bez jawnie tworzenia zmiennych dla każdej instancji studenta, tak:

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

Wszelkie rodzimy lub elegancki sposób, aby osiągnąć to w Swift?

Odpowiedz

8

masz kilka opcji w zależności od tego, jak chcesz aby skonfigurować ten typ i jaka składnia jest najwygodniejsza dla ciebie.

Można zdefiniować wygodny inicjator, który akceptuje właściwości, które chcesz ustawić. Przydatne, gdy ustawiasz te same właściwości przez cały czas, mniej przydatne, jeśli ustawiasz niespójny zestaw opcjonalnych właściwości.

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") 

Można zdefiniować inicjator wygody, który akceptuje blok, aby skonfigurować nowe wystąpienie.

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

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

Można naśladować tap metodę Ruby jako rozszerzenie, dzięki czemu można pracować na obiekcie w środku łańcucha metody.

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

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

Jeśli to ostatnie jest przydatna może chcesz być w stanie przyjąć tap na dowolnym obiekcie. Nie sądzę, że można to zrobić automatycznie, ale można zdefiniować domyślną implementację, aby ułatwić:

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

To jest genialne! – TruMan1

4

Jeśli klasa ma wymaganą initialiser, można użyć metody zamknięcia, aby ustawić właściwości Student przed zwróceniem nowy obiekt Student następująco:

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

Powodem szukam jest to więc mogę dodać kilka wystąpień do [.] array bez jawnie tworzenia zmiennych dla każdej instancji uczeń

nie jestem obeznany z C#, ale w Swift, można to zrobić tylko poprzez inicjowanie obiektów wewnątrz deklaracji tablicy:

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

Inne sugerowane podejścia są równie ważne, ale jeśli po prostu próbujesz wypełnić tablicę bez deklarowania zmiennych, Swift ułatwia to.

+1

Uczeń jest poza moją kontrolą i nie mogę go edytować. Znajduje się w innej strukturze. Mogę więc tylko ją dziedziczyć lub przedłużać. – TruMan1

1

Chciałem tylko zwrócić uwagę, że jeśli struktura może być niezmienne, można po prostu użyć struct zamiast class a dostaniesz niejawny inicjator za darmo:

Wystarczy wkleić do zabaw i Zmień strukturę na klasę, a zobaczysz, co mam na myśli.

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

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

Ah hah to świetnie !! Nie zdawałem sobie sprawy, że struktury mają to, ale nie inne typy. Dobrze wiedzieć!! Jedyną rzeczą jest to, że klasa Uczeń jest poza moją kontrolą ukryta w innej bibliotece, więc nie mogę zmienić jej źródła. – TruMan1

1

To tylko składniowym cukierek ale używam operatora niestandardową robić tego typu rzeczy:

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() } 
    ]