Menu

Category

Archive

logo


The Swift Programming Language ~ Inheritance

2014-06-19 12:00:00 +0900
  • このエントリーをはてなブックマークに追加

iBooks にある "The Swift Programming Language" の勉強メモ。Objective-C と C を普段書いている自分から、ちょっと馴染みがないものを特にまとめておきます。目次は こちら

今回は、Inheritance に関して。

Inheritance

1. ベースクラス

クラスは、他のクラスを継承することができます。継承により、メソッド、プロパティ、またサブスクリプト等の特性を継承したクラスを作成できます。

 1 class Vehicle {
 2     var numberOfWheels: Int
 3     var maxPassengers: Int
 4     func description() -> String {
 5         return "\(numberOfWheels) wheels; up to \(maxPassengers) passengers"
 6     }
 7     init() {
 8         numberOfWheels = 0
 9         maxPassengers = 1
10     }
11 }

Swift では、NSObject のようなすべてのクラスのベースとなるクラスはありません。つまり、継承をせずにクラスを作成したクラスは、自動的にそのコンテキストにおいてベースクラスになります。上記の Vehicle クラスはこの記事の中でこれから紹介する例の全てのクラスのベースクラスになります。

2. サブクラス

クラスを継承するには、サブクラス宣言時にクラス名の名前の後に : で区切り、継承されるクラス名を書きます。

 1 class Bicycle: Vehicle {
 2     init() {
 3         super.init()
 4         numberOfWheels = 2
 5     }
 6 }
 7 
 8 class Tandem: Bicycle {
 9     init() {
10         super.init()
11         maxPassengers = 2
12     }
13 }

Objective-C と違い、initializer はデフォルトで継承されません。

3. オーバーライド

サブクラスは、継承されたインスタンスメソッド、クラスメソッド、インスタンスプロパティ、サブスクリプトを独自に実装し直すことができます。そのためには、override キーワードを使用します。もし、override を使用せずに、オーバーライドを試みるとコンパイラエラーになります。

また、スーパークラスのメソッドやプロパティ、サブスクリプトをオーバーライドする際に、スーパークラスの実装をその中で使いたい場合があると思います。この時には、super キーワードを使用してアクセスできます。この Car サブクラスの例では、description メソッドをオーバーライドしています。また、この サブクラスの例では、description の中では、スーパークラスの サブクラスの例では、description メソッドを使用しています。

 1 class Car: Vehicle {
 2     var speed: Double = 0.0
 3     init() {
 4         super.init()
 5         maxPassengers = 5
 6         numberOfWheels = 4
 7     }
 8     override func description() -> String {
 9         return super.description() + "; "
10             + "traveling at \(speed) mph"
11     }
12 }

プロパティをオーバーライドをすることもできます。サブクラス内で、独自のセッター・ゲッターを作成できます。また、プロパティオブザーバー を追加することもできます。

まずは、独自のゲッター・セッターをみていきます。継承されたプロパティが Stored property でも、Computed property でも、ゲッター・セッターを作成できます。ゲッター・セッターを実装することにより、スーパークラスの read-only のプロパティを read-write プロパティに変更することができます。しかし、read-write プロパティを read-only プロパティに変更することはできません。プロパティをオーバーライドする際に、セッターを実装する時にはゲッターも実装しなければなりません。もし、ゲッターを修正する必要がない場合には、ただスーパークラスのプロパティを返します。下記の SpeedLimitedCar はこのセッターだけ変更したい場合の例です。

 1 class SpeedLimitedCar: Car {
 2     override var speed: Double  {
 3     get {
 4         return super.speed
 5     }
 6     set {
 7         super.speed = min(newValue, 40.0)
 8     }
 9     }
10 }

次に、プロパティオブザーバーのオーバーライドをみていきます。継承されたコンスタント Stored プロパティ、継承された read-only Computed プロパティには、プロパティオブザーバーを追加することはできません。なぜならば、これらの値に対して新しく値を設定することは許されていません。したがって、willSetdidSet を実装することはありません。また、セッターのオーバーライドとプロパティオブザーバーは、同時に作成できません。プロパティの値の変化を監視し、さらにセッターをオーバーライドしている場合には、この監視する機能をそのオーバーライドしたセッターのコードの中に書いてください。

 1 class AutomaticCar: Car {
 2     var gear = 1
 3     override var speed: Double {
 4     didSet {
 5         gear = Int(speed / 10.0) + 1
 6     }
 7     }
 8     override func description() -> String {
 9         return super.description() + " in gear \(gear)"
10     }
11 }

この AutomaticCar の例では、プロパティオブザーバーを追加しています。スーパークラスの speed プロパティが変更された場合に、AutomaticCar のプロパティである gear を変更しています。

4. オーバーライドの防止

他の言語と同じように、メソッド・プロパティ・サブスクリプトがオーバーライドされることを禁止することができます。@final キーワードを使用します。例えば、@final var@final func@final class func@final subsript と使います。このように @final されたものをサブクラスの中でオーバーライドしようとすると、コンパイルエラーになります。

また、クラス自体を継承されることが不適切な場合には、class キーワードの前に @fianl を使用します。これにより、このクラスからサブクラスを作成することができなくなります。