1.イニシャライザの基本
まずストアドプロパティtoとコンピューテドプロパティbodyを持つ構造体Greetを定義します。(sample1)
sample1
struct Greet{ let to:String var body:String{ return "Hello,\(to)!!!!!" } init(to:String){ //←がイニシャライザ self.to=to } }
init(引数){初期化処理}
の部分がイニシャライザの定義。
次に構造体Greetのインスタンスを生成します。(sample2)
sample2
struct Greet{ let to:String var body:String{ return "Hello,\(to)!!!!!" } init(to:String){ self.to=to } } let gr1=Greet(to:"address1") //インスタンス生成。この時自動的に //イニシャライザが実行される。 print(gr1.body)
Hello,address1!!!!!
Greet型のインスタンス生成時に、引数toに文字列”address1″が渡されてイニシャライザが呼び出されます。コンピューテドプロパティbodyにアクセスすると、イニシャライザにより初期化されたストアドプロパティtoを参照して文字列
Hello,address1!!!!!
を返します。
ためしに引数無しでGreet型のインスタンスを生成してみると、(sample3)
sample3
struct Greet{ let to:String var body:String{ return "Hello,\(to)!!!!!" } init(to:String){ self.to=to } } let gr1=Greet() //コンパイルエラー
main.swift:13:15: error: missing argument for parameter 'to' in call let gr1=Greet() ^ to: <#String#> main.swift:8:5: note: 'init(to:)' declared here init(to:String){
コンパイルエラーになります。イニシャライザ呼び出し時(インスタンス生成時)に引数toが必要なのに渡されていない」ということですね。
もうひとつ試しにイニシャライザの引数に数値をセットしてインスタンスを生成を試みます。(sample4)
sample4
struct Greet{ let to:String var body:String{ return "Hello,\(to)!!!!!" } init(to:String){ self.to=to } } let gr1=Greet(to:345)
main.swift:13:18: error: cannot convert value of type 'Int' to expected argument type 'String' let gr1=Greet(to:345) ^~~
コンパイルエラーです。「渡されたInt型の値345をString型に型変換できない」と言ってますね。
インスタンスの全てのプロパティは、インスタンス化完了までに初期化されている(値がセットされている)必要があります。イニシャライザに適切な型を指定してプロパティの初期化処理を記述しておけば、「プロパティの初期化が正しい型の値によりもれなく行われているか」をコンパイラが自動的にチェックしてくれる、ということですね。
また別の試みとして、新しいプロパティpropを付け加えてみます。(sample5)
sample5
struct Greet{ let to:String let prop:String //←ストアドプロパティpropを追加 var body:String{ return "Hello,\(to)!!!!!" } init(to:String){ //イニシャライザはそのまま self.to=to } } let gr1=Greet(to:"address1") //コンパイルエラー
main.swift:11:5: error: return from initializer without initializing all stored properties } ^ main.swift:4:9: note: 'self.prop' not initialized let prop:String
Greet型の定義にプロパティpropを加えましたので、プロパティは
to
prop
の二つになりました。しかしイニシャライザは変更していないので、toの初期化しかできない状態ですね。結果はコンパイルエラーです。
「すべてのストアドプロパティを初期化するイニシャライザが必要」という警告ですね。ですのでエラーが出なくするには、sample6のように構造体定義時に初期値をセットする(sample6)
sample6
struct Greet{ let to:String let prop:String="prop" //←ここでpropプロパティを初期化 var body:String{ return "Hello,\(to)!!!!!\nprop is'\(prop)'" } init(to:String){ //←toプロパティはイニシャライザで初期化 self.to=to } } let gr1=Greet(to:"address1") print(gr1.body)
Hello,address1!!!!!
prop is'prop'
あるいは、イニシャライザでpropプロパティも初期化するように変更する(sample7)
sample7
struct Greet{ let to:String let prop:String var body:String{ return "Hello,\(to)!!!!!\nprop is'\(prop)'" } //↓すべてのストアドプロパティが初期化されるようにイニシャライザを修正 init(to:String,prop:String){ self.to=to self.prop=prop } } let gr1=Greet(to:"address1",prop:"prop2") print(gr1.body)
Hello,address1!!!!!
prop is'prop2'