2016-01-22 1 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ため。

Swiftのようなことができたら、私はdocumentationに見つかりませんでした。そうでない場合、extensionsを使用して、初期化中にStudentクラスを拡張してプロパティ値を割り当てる方法がありますか?

私はこれを探していた理由は、私はこのように、明示的に各学生のインスタンスの変数を作成せずに配列にインスタンスの束を追加することができます:達成する

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

任意のネイティブまたはエレガントな方法これはスイフトで?

答えて

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

その最後の1が有用である場合は、任意のオブジェクトに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

あなたのクラスは何の必要な初期化子を持っていない場合は、次のように新しい学生オブジェクトを返す前に学生のプロパティを設定するために閉鎖メソッドを使用することができます。

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

Studentクラスがコントロールできず、編集できません。それは別のフレームワークにあります。だから私はそれを継承または拡張することしかできません。 – TruMan1

1

私はちょうどあなたの構造は不変することができた場合、あなただけのstructではなくclassを使用することができますし、あなたが自由のための暗黙の初期化子を得るだろうことを指摘したかった:

だけの遊び場にこれを貼り付け、構造体をクラスに変更すると、私の意図がわかります。

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

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

ああ、それは素晴らしいです!構造体がこれを持っていて他の型は持っていなかったことに気付かなかった。知っておいてよかった!!唯一のことは、Studentクラスが他のライブラリに埋め込まれているため、ソースを変更できないことです。 – 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() } 
    ] 
関連する問題