Swift programming language の Initialization の章が分かりにくいので、初期化2に簡単にまとめます。
イニシャライザー
// 最も簡単なイニシャライザー class Animal { var name: String = "" var nakigoe: String = "" init() { } } // init でプロパティ値を初期化 class Animal { var name: String var nakigoe: String init() { name = "" nakigoe = "" } } // initの書式 // init(ラベル名 引数名: 型) { 式 } let animal = Animal(animalName: "animal") class Animal { var name: String var nakigoe: String? init(animalName name: String) { self.name = name } } // 引数ラベルのない初期化パラメーター let animal = Animal("animal") class Animal { var name: String var nakigoe: String? init(_ name: String) { self.name = name } } // すべてのプロパティのデフォルト値が提供されている場合、initは省略できる // nakigoeは、オプショナルString のため、デフォルト値 nil が与えられる class Animal { var name: String = "" var nakigoe: String? } // メンバーの初期化例 let animal = Animal(name: "animal", nakigoe: nil) class Animal { var name: String = "" var nakigoe: String? = nil init(name: String, nakigoe: String?) { self.name = name self.nakigoe = nakigoe } }
指定イニシャライザとコンビニエンスイニシャライザ
// 指定イニシャライザ // すべてのクラスには、少なくとも1つの指定イニシャライザが必要 init(parameters) { statements } // コンビニエンスイニシャライザは二次的なもの // クラスのイニシャライザをサポートする convenience init(parameters) { statements }
- ルール1 指定イニシャライザは、直接のスーパークラスから指定イニシャライザを呼び出す必要があります。
- ルール2 コンビニエンスイニシャライザは、同じクラスから別のイニシャライザを呼び出す必要があります。
- ルール3 コンビニエンスイニシャライザは、最終的に指定イニシャライザを呼び出す必要があります。
class Animal { var name: String var nakigoe: String? // 指定イニシャライザー init(_ name: String) { self.name = name } // コンビニエンスイニシャライザー convenience init(name: String, nakigoe: String) { self.init(name) self.nakigoe = nakigoe } func naku(){ print(nakigoe ?? "") } }
// スーパークラス内のコンビニエンスイニシャライザー convenience init(name: String, nakigoe: String) // サブクラスからスーパークラスのコンビニエンスイニシャライザーを // オーバーライドしようとすると、次のエラーが発生する override convenience init(name: String, nakigoe: String) // Initializer does not override a designated initializer from its superclass
2フェーズ初期化
フェーズ1では、すべての格納プロパティに初期値が割り当てられます。
フェーズ2では、各クラスに格納されたプロパティをカスタマイズできる。
class Animal { var name: String var nakigoe: String? init(_ name: String) { self.name = name } convenience init(name: String, nakigoe: String) { self.init(name) self.nakigoe = nakigoe } func naku(){ print(nakigoe ?? "") } } class Dog: Animal { override init(_ name: String) { // フェーズ1 スーパークラスのイニシャライザーを呼ぶ必要がある super.init(name) // フェーズ2 カスタマイズできる self.nakigoe = "wanwan" } } // super.init を呼ばないと、次のエラーになる // 'self' used in property access 'nakigoe' before 'super.init' call // 'super.init' isn't called on all paths before returning from initializer
自動的なイニシャライザの継承
// ルール1 // サブクラスが指定イニシャライザを定義していない場合、 // 自動的に Animal のinit が継承される class Animal { var name: String var nakigoe: String? init(_ name: String) { self.name = name self.nakigoe = "designated wanwan" } convenience init(name: String, nakigoe: String) { self.init(name) self.nakigoe = "convinience wanwa" } func naku(){ print(nakigoe ?? "") } } class Dog: Animal { // サブクラスが指定イニシャライザを定義していない場合、 // 自動的に Animal のinit が継承される } // let dog = Dog("Snoopy") // dog.naku() // 結果: designated wanwan
// ルール2 // サブクラスがすべてのスーパークラスの指定イニシャライザの実装を提供する場合 // スーパークラスのすべてのコンビニエンスイニシャライザを自動的に継承する class Animal { var name: String var nakigoe: String? init(_ name: String) { self.name = name self.nakigoe = "designated wanwan" } convenience init(name: String, nakigoe: String) { self.init(name) self.nakigoe = nakigoe } func naku(){ print(nakigoe ?? "") } } class Dog: Animal { override init(_ name: String) { super.init(name) self.name = name self.nakigoe = "designated wanwan" } } // let dog = Dog(name: "Snoopy", nakigoe: "superclass's convinience init wanwan") // dog.naku() // 結果: superclass's convinience init wanwan
失敗可能なイニシャライザ
失敗可能なイニシャライザは、初期化する型のオプションの値を作成します。失敗可能なイニシャライザ内に return nil を書き込んで、初期化の失敗をトリガーします。
if let animal = Animal("") { // 初期化に失敗して、animal はnil になるため、次の行は実行されない animal.naku() } class Animal { var name: String var nakigoe: String? // 失敗可能なイニシャライザ init?(_ name: String?) { if name == "" { // return nil で初期化に失敗したことをトリガーする return nil } self.name = name! self.nakigoe = "designated wanwan" } func naku(){ print(nakigoe ?? "") } }
クラス、構造体、または列挙体の失敗可能なイニシャライザは、同じクラス、構造体、または列挙体から別の失敗可能なイニシャライザに委任できます。
サブクラスでスーパークラスの失敗可能なイニシャライザをオーバーライドできます。また、スーパークラスの初期化に失敗しても、初期化に失敗しないサブクラスでオーバーライドできます。
init!失敗可能なイニシャライザ
暗黙的にアンラップされたオプションのインスタンスを作成する、失敗可能なイニシャライザ init! を定義できます。
if let animal = Animal("") { animal.naku() } class Animal { var name: String var nakigoe: String? init!(_ name: String?) { if name == "" { self.name = "default name" } self.name = name! self.nakigoe = "designated wanwan" } func naku(){ print(nakigoe ?? "") } }
必須イニシャライザ
class Animal { var name: String var nakigoe: String? // すべてのサブクラスがそのイニシャライザを実装する必要があることを示す required init(name: String) { self.name = name self.nakigoe = "wanwan" } } class Dog: Animal { // override は不要 required init(name: String) { super.init(name: name) self.name = "dog: " + name }