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

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

2. サブクラス

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

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

class Tandem: Bicycle {
    init() {
        super.init()
        maxPassengers = 2
    }
}

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

3. オーバーライド

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

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

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

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

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

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

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

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

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

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

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

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