楽水

人々の創造が自由に表現できる舞台づくり

Swift

Swiftの継承についてわかりやすく解説

投稿日:2020年10月4日 更新日:


クラスは、別のクラスからメソッド、プロパティ、および他の特徴を継承することができます。
あるクラスが別のクラスから継承するとき、継承するクラスをサブクラス、継承されるクラスをスーパークラスと呼びます。
今回は、Swiftの継承について以下の観点で解説します。

  • ベースクラスの定義
  • サブクラス化
  • オーバーライド

参考本
[改訂新版]Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 WEB+DB PRESS plus

ベースクラスの定義

別のクラスから継承されるクラスのことを、ベースクラスと呼びます。
次の例では、ベースクラスVehicle を定義しています。

class Vehicle {
 var currentSpeed = 0.0
 var description: String {
 return “traveling at \(currentSpeed) miles per hour”
}
 func makeNoise() {
  // 何もしない – 乗り物は必ずしも音を立てない
 }
}

ベースクラス Vehicle は、makeNoise メソッドも定義しています。
このメソッドは、ベースの Vehicle インスタンスでは実際には何もしませんが、後で Vehicle のサブクラスによってカスタマイズされます。
ベースクラス Vehicle を実行します。

let someVehicle = Vehicle()
print(“Vehicle: \(someVehicle.description)”)
// Vehicle: traveling at 0.0 miles per hour

サブクラス化

サブクラスは、既存のクラスから特徴を継承し、改良することができます。
サブクラスにスーパークラスがあることを示すために、サブクラス名の後にスーパークラス名を記述し、コロンで区切ります。

class SomeSubclass: SomeSuperclass {
 // サブクラスの定義
}

次の例では、Vehicle をスーパークラスとするサブクラス Bicycle を定義しています。

class Bicycle: Vehicle {
 var hasBasket = false
}

新しい Bicycle クラスは、currentSpeed や description プロパティと makeNoise() メソッドなどの、Vehicle のすべての特徴を自動的に獲得します。
継承する特徴に加えて、Bicycle クラスは新しいストアドプロパティ hasBasket をデフォルト値 false(プロパティを Bool 型と推論)で定義しています。
サブクラスをさらにサブクラス化することもできます。

オーバーライド

サブクラスは、スーパークラスから継承したインスタンスメソッド、タイプメソッド、インスタンスプロパティ、タイププロパティ、およびサブスクリプトの独自実装を持つことができます。
これをオーバーライドと呼びます。
継承した特徴をオーバーライドするには、override キーワードをオーバーライドする定義の前に付けます。
サブクラスでメソッド、プロパティ、サブスクリプトをオーバーライドするとき、オーバーライドの一部としてスーパークラスの実装を利用したい場合、スーパークラスのメソッド、プロパティ、サブスクリプトに super を付けてアクセスします。
例えば、オーバーライドされたメソッド someMethod() は、そのオーバーライド実装内で super.someMethod() とすることでスーパークラスの someMethod() を呼び出すことができます。

メソッドのオーバーライド

次の例では、Vehicle の新しいサブクラス Train を定義し、Vehicle から継承した makeNoise() メソッドを Train はオーバーライドしています。

class Train: Vehicle {
 override func makeNoise() {
  print(“Choo Choo”)
 }
}

Train のインスタンスを生成して makeNoise() メソッドを呼び出す場合、サブクラス Train のメソッドが呼び出されます。

let train = Train()
train.makeNoise()
// Prints “Choo Choo”

プロパティのオーバーライド

インスタンスプロパティやタイププロパティに独自の getter や setter を持たせることや、プロパティ値の変更を監視するためにプロパティオブザーバを追加することで、継承したプロパティをオーバーライドすることができます。
次の例では、Vehicle のサブクラスである新しいクラス Car を定義しています。Car クラスには、デフォルトの整数値が 1 のストアドプロパティ gear を定義しています。
Car クラスは、Vehicle から継承する description プロパティを、現在のギアを含む説明となるようにオーバーライドもしています。

class Car: Vehicle {
 var gear = 1
 override var description: String {
  return super.description + ” in gear \(gear)”
 }
}

Car クラスのインスタンスを生成して gear と currentSpeed を設定した場合、description プロパティは Car クラス内で定義した付加情報のある説明を返すようになります。

let car = Car()
car.currentSpeed = 25.0
car.gear = 3
print(“Car: \(car.description)”)
// Car: traveling at 25.0 miles per hour in gear 3

プロパティオブザーバのオーバーライド

継承したプロパティにプロパティオブザーバを追加することができます。
これによって、プロパティの実装にかかわらず、継承したプロパティ値の変更時に通知されるようにすることができます。
次の例では、Car のサブクラスである新しいクラス AutomaticCar を定義しています。
AutomaticCar クラスは、現在速度をもとに自動的に適切なギアを選択する自動変速装置を持つ車を表現しています。

class AutomaticCar: Car {
 override var currentSpeed: Double {
  didSet {
   gear = Int(currentSpeed / 10.0) + 1
  }
 }
}

AutomaticCarを実行してみます。

let automatic = AutomaticCar()
automatic.currentSpeed = 35.0
print(“AutomaticCar: \(automatic.description)”)
// AutomaticCar: traveling at 35.0 miles per hour in gear 4

AutomaticCar インスタンスの currentSpeed プロパティに設定したとき、プロパティの didSet オブザーバが新しい速度に合う適切なギアをインスタンスの gear プロパティに設定します。
具体的には、プロパティオブザーバは新しい currentSpeed の値を 10 で割り、整数に切り捨て、1 を足したギアを選択します。速度 35.0 は、ギア 4 となります。

オーバーライドの防止

メソッド、プロパティ、サブスクリプトがオーバーライドされることを final で防ぐことができます。
そうするには、メソッド、プロパティ、サブスクリプトのキーワードの前に final を、final var, final func, final class func, final subscript のように記述します。

以上、今回は、Swiftの継承について解説しました。

-Swift
-, ,

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

Swiftのメソッドをわかりやすく解説

メソッドは、特定の型に関連した関数です。 クラス、構造体、列挙型はすべて、型のインスタンスを扱う特定のタスクと機能を持つインスタンスメソッドを定義することができます。 また、クラス、構造体、列挙型は、 …

Swiftのプロパティ【プロパティオブザーバーなどをわかりやすく解説】

プロパティは値と特定のクラスや構造体、列挙型を結び付けます。 Swiftのプロパティには、値を保持するプロパティだけではなく様々な種類のプロパティがあります。 今回は、Swiftのプロパティについて以 …

Swiftのクロージャについてわかりやすく解説

Swiftのクロージャって何? いまひとつわからない、という方むけに、今回は、Swiftのクロージャについて以下の観点で丁寧に解説します。 Swiftのクロージャとは何か Swiftのクロージャ式 S …

Swiftクロージャによる強い参照の循環参照とその解決

Swiftのメモリ管理 では、 2 つのクラスインスタンスのプロパティが互いに強い参照を持つことで、どのようにして強い参照の循環参照が生成されるのかを見てきました。 また、強い参照の循環参照を切るため …

Swiftのクラスと構造体をわかりやすく解説

Swiftを学ぶ過程で、クラスと構造体は何が違うのか知りたいと考える人もいると思います。 そこで、今回は、以下の観点でSwiftのクラスと構造体について解説します。 クラスと構造体の定義 クラスと構造 …