継承
Swiftのクラスは、Objective-Cと同じような方法で継承を行うことが可能です。継承元となるスーパークラスの名前を、宣言するサブクラス名の後ろに「:」(コロン)に続けて記します。
class SomeSuper {
var index: Int = 1
}
class SomeSub : SomeSuper {
var name: String = "default"
}
他の特徴もさることながら、Swiftのクラスは宣言時に基底クラス(JavaでいうところのObjectクラス)を継承せずに、それぞれが基底クラスとして宣言されるという特徴を持っています。インスタンスの同値性や、Stringに変換してのログ出力などは、基底クラスのメソッドを継承するのではなく、同値性の特徴を持ったプロトコル(Equatable)やStringに変換するためのプロトコル(Printable)に準拠させることによって行います。
なお、ストラクチャは継承機能を持っていませんが、プロトコルに準拠させることが可能です。
つまり、Objective-Cでは、isEqualやhash、descriptionといったNSObjectクラスに宣言されたメソッドをオーバーライドすることで同値性の判定などを実装しましたが、Swiftでは、これらの機能の実装一つ一つをプロトコルで行えるということです。こちらは次回以降のプロトコルを取り上げる回で解説します。
overrideキーワード
Objective-Cでは、サブクラスを見ただけではスーパークラスからオーバーライドしたメソッドかどうか分かりませんでした。Swiftでは、オーバーライドしたメソッドにはoverrideキーワードを付ける必要があり、意図しないオーバーライドを防ぐことができるようになりました。
次の例は、先ほどのSomeSuperクラスにprintInfo()というメソッドを用意して、SomeSubクラスでオーバーライドさせています。
class SomeSuper {
var index: Int = 1
func printInfo() {
println("index : \(index)")
}
}
class SomeSub : SomeSuper {
var name: String = "name"
override func printInfo() {
super.printInfo()
println("name : \(name)")
}
}
let superVal = SomeSuper()
superVal.printInfo() // index : 1
let subVal = SomeSub()
subVal.printInfo() // index : 1 name : name
なお、この例ではsuperキーワード経由で継承元クラスのメソッドを呼び出しています。この挙動は、Objective-Cから変化がありません。
プロパティに関しても、サブクラスでget/set/willSet/didSetの挙動を変えたいときには、overrideキーワードをメソッド宣言と同様に付けることでオーバーライドができます。
final属性
Objective-Cでサブクラス化を禁止する場合、イニシャライザでの動作時型検査で例外を投げるなどの方法がありました。Swiftでは、継承したクラスでオーバーライドさせたくない(禁止したい)プロパティやメソッドにはfinal修飾子を付けます。final修飾子が付けられたメソッドをオーバーライドしようとすると、コンパイル時にエラーが出力されます。
class SomeSuper {
var index: Int = 1
final var name: String {
return "index : \(index)"
}
}
class SomeSub : SomeSuper {
override var name: String { // コンパイル時のエラー
return "some string"
}
}
この仕組みにより、クラスの使用者に向けて、継承禁止の意図をより明確に伝えることが可能になりました。また、クラスそのものを継承させたくない場合は、classキーワードの前に修飾子を付けることで継承を禁止できます。
