久しぶりにSwiftのイニシャライザを復習したので、そのときに思ったことや新たに知ったことを、つれづれなるままに書いていきます。つれづれなるままなので「〜思います」系の表現があります。
環境はSwift5.0です。
2つのクラスに継承関係があるとき、サブクラスのinitでは、親のinitを呼ぶ前に自分のところで定義したものを初期化するのはなぜか
class A1 {
var name: String
init() {
print("super")
name = "unknown"
}
}
class B1: A1 {
var age: Int
override init() {
print("sub")
super.init() //エラー Property 'self.age' not initialized at super.init call
age = 0
}
}
上の例ではB1のageが初期化されていないとエラーが出ます。初めてこの仕様を見たときは不思議な感じがしました。親を固めて(初期化して)から子を固めるべき、そう感じたからです。
しかし、B1のageが初期化されていない使い方が許されると、次の例ではサブクラスが固まってないのにサブクラスのsomeFunction()が呼び出されてしまうので、こういうのを防ぐ理由もあるかなと気が付きました。
class A1 {
var name: String
init() {
print("super")
name = "unknown"
someFunction()
}
func someFunction() {
print("super someFunction")
}
}
class B1: A1 {
var age: Int
override init() {
print("sub")
super.init()
age = 0
}
override func someFunction() {
print("sub someFunction")
super.someFunction()
}
}
2つのクラスに継承関係があるとき、親のコンビニエンスinitと同じ引数のinitをサブクラスで指定initとして定義するときの挙動
今回いろいろ調べていてわかったことがあります。誤解を恐れずに書くと
2つのクラスに継承関係があって親が指定initとコンビニエンスinitを持つときに、サブクラスで親と同じ指定initを定義しないで、サブクラスでその指定initが自動生成されると同時に親クラスのコンビニエンスinitも自動生成される条件が整った状況で、親クラスのコンビニエンスinitと同じ引数のinitをサブクラスで指定initとして定義すると、例えばoverrideをつけるように催促するエラーが出ることもなく、コンパイルが通る
です。
class A2 {
var name: String
init(name: String) {
print("super 1")
self.name = name
}
convenience init() {
print("super 2")
self.init(name: "unknown")
}
}
class B2: A2 {
init() {
print("sub")
super.init(name: "unknown")
}
}
var b2 = B2()
//出力
//sub
//super 1
2つのクラスに継承関係があって親の指定initが2つあるとき、サブクラスでその片方をコンビニエンスinitとして定義するときの挙動
わかったことの2つめは
2つのクラスに継承関係があって親クラスが指定initを2つ持つときに、その片方と同じ引数のinitをサブクラスでコンビニエンスinitとして定義すると、もう片方の指定initは自動生成されて、サブクラスで定義したコンビニエンスinitはoverrideをつけるように催促され、overrideをつけるとそのコンビニエンスinitからself.init()で自動生成された指定initが呼び出せる
です。
class A2 {
var name: String
init(name: String) {
print("super 1")
self.name = name
}
init() {
print("super 2")
self.name = "unknown"
}
}
class B2: A2 {
convenience override init() {
print("sub")
self.init(name: "unknown")
}
}
var b2 = B2()
//出力
//sub
//super 1
おわりに
*** で詳しく書いてあります。などの情報があれば、よろしくおねがいします。