Swiftでは、すべての非optionalタイプのプロパティはインスタンスの初期化が完了する前に初期化される必要があります。そのために、designated(主要)、convenience(補助)、およびrequired(継承者に必須)イニシャライザが使用されます。
例:
class Vehicle { let numberOfWheels: Int required init(numberOfWheels: Int) { self.numberOfWheels = numberOfWheels } } class Car: Vehicle { let brand: String // Designated イニシャライザ required init(numberOfWheels: Int) { self.brand = "Unknown" super.init(numberOfWheels: numberOfWheels) } // Convenience convenience init() { self.init(numberOfWheels: 4) self.brand = "Ford" } }
主なポイント:
designatedイニシャライザを使用する際、サブクラスとスーパークラスのプロパティを初期化する順序はどうなるべきですか?
**回答:**サブクラスのすべてのプロパティは、スーパークラスのdesignatedイニシャライザ(super.init)を呼び出す前に初期化される必要があります。そうしないとコンパイルエラーになります。super.initの後には、サブクラスの新しいstoredプロパティを初期化することはできず、それらを使用するだけです。
class Parent { let parentProp: Int init(prop: Int) { parentProp = prop } } class Child: Parent { let childProp: String init(prop: Int, childProp: String) { self.childProp = childProp // まず自分のプロパティを super.init(prop: prop) // 次に親を } }
物語
開発者がconvenienceイニシャライザ内で、designatedを呼び出さずにrequireプロパティに直接値を割り当てようとしました。その結果、プロパティは異なる値で2回初期化され、テスト時に予期しない動作を引き起こしました。
物語
深いクラス階層の継承時にrequired initを宣言し忘れ、その結果、リフレクションを介して派生タイプを正しく初期化できなくなり、JSONモデルのデシリアライズ時にクラッシュしました。
物語
Vehicleクラスを拡張する際にスーパークラスのdesignatedイニシャライザが呼び出されなかったため、必須のプロパティの初期化が不正となり、データスキーマ更新後に運用中にクラッシュを引き起こしました。