2016-01-22 98 views
6

是否有一種方法可以將屬性值分配給類實例,即使它不是init構造函數中的參數?例如,在C#中我可以這樣做:Swift中的一步對象創建和屬性初始化?

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

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

通告student2我可以在初始化過程中仍然賦值即使是在類沒有構造函數。

我找不到documentation如果你能爲Swift做這樣的事情。如果沒有,有沒有辦法使用extensions擴展Student類來在初始化期間分配屬性值?

我正在尋找這是這樣我就可以了一堆實例添加到一個數組,而不爲每一個學生的實例明確地創建變量,像這樣的理由:

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

任何本地或優雅的方式來實現這在Swift中?

回答

8

你取決於你如何想幾個選項配置此類型以及最適合您的語法。

您可以定義一個方便的初始化程序,它接受您要設置的屬性。如果您始終設置相同的屬性,這很有用,如果您設置了一組不一致的可選屬性。

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

您可以定義一個便捷初始值設定項,它接受一個塊來配置新的實例。

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

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

你可以模仿Ruby的tap方法的擴展,所以你可以在方法鏈中間的對象進行操作。

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

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

如果最後一個是你可能希望能夠採取tap任何對象上有用。我不認爲你可以自動做到這一點,但你可以定義一個默認的實現,使其更容易:

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

這是輝煌! – TruMan1

4

如果你的類沒有必要的初始化器,你可以使用一個封閉方法返回新的Student對象如下之前設置的學生屬性:

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

我在尋找這樣做的原因是這樣我就可以了一堆實例添加到[]數組沒有爲每個學生例如明確創建變量

我不熟悉C#,但是在斯威夫特,你可以這樣做只是通過初始化數組聲明中的對象:

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

建議的其他方法都是同樣有效的,但如果您只是試圖在未聲明任何變量的情況下填充數組,Swift使這一切變得容易。

+1

學生課不在我的控制之下,我無法編輯它。它駐留在另一個框架中。所以我只能繼承或擴展它。 – TruMan1

1

我只是想指出的是,如果你的結構是不可變的,你可以只使用一個struct而非class,你會得到一個隱含的初始化免費:

就粘貼到一個遊樂場和將結構更改爲類,你會明白我的意思。

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

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

啊哈,真是太棒了!沒有意識到結構有這個,但沒有其他類型。很高興知道!!唯一的問題是學生班不在我的控制之下,埋在另一個圖書館裏,所以我無法修改它的來源。 – TruMan1

1

這只是語法糖,但我使用自定義操作做這種事情:

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