Swift 5.8 日本語化計画 : Swift 5.8
継承
クラスは別のクラスからメソッド、プロパティ、およびその他の特性を 継承 できます。1つのクラスが別のクラスから継承する場合、継承するクラスは サブクラス として知られており、継承されるクラスは、その スーパークラス として知られています。継承は、Swift では他の型からクラスを区別する基本的な動作です。
Swift のクラスは、それらのスーパークラスに属するメソッド、プロパティ、およびサブスクリプトを呼び出し、アクセスでき、それらの動作を洗練または変更するために、それらのメソッド、プロパティ、およびサブスクリプトの独自にオーバーライドするバージョンを提供できます。Swift は上書き(オーバーライド) が一致するスーパークラスの定義を持っている上書きの定義であることをチェックして正しいことを確認するのに役立ちます。
また、クラスはプロパティの値が変更された時に通知するように、継承されたプロパティにプロパティ監視者を追加することもできます。プロパティ監視者は、それが元々格納されたプロパティとしてかまたは計算されたプロパティとして定義されているかに関わりなく、任意のプロパティに追加できます。
基本クラスの定義
別のクラスから継承していない全てのクラスは 基本クラス として知られています。
以下の例では、vehicle と言う基本クラスを定義しています。この基本クラスは、(Double のプロパティ型を推論して) 0.0 のデフォルト値で currentSpeed という格納されたプロパティを定義しています。currentSpeed プロパティの値は、vehicle の説明を作成するために読み取り専用の description と言う計算された String プロパティで使用されます。
Vehicle 基本クラスは makeNoise と言うメソッドも定義しています。このメソッドは、実際には基本の Vehicle インスタンスには何もしていませんが、後で Vehicle のサブクラスによってカスタマイズされます:
- class Vehicle {
- var currentSpeed = 0.0
- var description: String {
- return "traveling at \(currentSpeed) miles per hour"
- }
- func makeNoise() {
- // do nothing - an arbitrary vehicle doesn't necessarily make a noise
- }
- }
空の括弧が続く型の名前として書かれる、イニシャライザ構文 で、Vehicle の新しいインスタンスを作成します。
新しい Vehicle インスタンスを作成すると、vehicle の現在の速度を人間が読める記述にして印刷するために、 description プロパティにアクセスできます。
- print("Vehicle: \(someVehicle.description)")
- // Vehicle: traveling at 0.0 miles per hour
Vehicle クラスは、任意の車両 (vehicle) のための共通の特性を定義していますが、それ自体はあまり便利ではありません。それをより便利にするには、車両 (vehicle) のより具体的な種類を記述するためにそれを洗練する必要があります。
サブクラス化
サブクラス化 は、既存のクラス上に新しいクラスを基づかせる行為です。サブクラスは、既存のクラスから特性を継承し、それをあなたは洗練することができます。また、サブクラスに新しい特性を追加する事もできます。
サブクラスがスーパークラスを持っていることを示すには、コロンで区切ってスーパークラスの名前の前にサブクラス名を書きます:
- class SomeSubclass: SomeSuperclass {
- // subclass definition goes here
- }
以下の例では、そのスーパークラスが Vehicle である Bicycle と言うサブクラスを定義しています。
- class Bicycle: Vehicle {
- var hasBasket = false
- }
新しい Bicycle クラスは、その currentSpeed と description プロパティとその makeNoise()メソッドのような、Vehicle の特性を自動的にすべて得ます。
それが継承する特性に加えて、Bicycle クラスはデフォルト値で false (プロパティで Bool の型を推論) を持つ、新しい格納されたプロパティ、hasBasket を定義します。
デフォルトでは、作成する新しい Bicycle インスタンスは全てバスケットを持っていません。そのインスタンスが作成された後は、特定の Bicycle インスタンスに対して hasBasket プロパティを true に設定することができます。
- let bicycle = Bicycle()
- bicycle.hasBasket = true
また、Bicycle のインスタンスの、継承した currentSpeed プロパティを変更し、インスタンスの継承した description プロパティを照会することもできます。
- bicycle.currentSpeed = 15.0
- print("Bicycle: \(bicycle.description)")
- // Bicycle: traveling at 15.0 miles per hour
サブクラスは、それ自体サブクラス化できます。次の例では、"タンデム" として知られている2人乗り自転車のための Bicycle のサブクラスを作成しています。
- class Tandem: Bicycle {
- var currentNumberOfPassengers = 0
- }
Tandem は、Bicycle からプロパティとメソッドをすべて継承し、順番に Vehicle からプロパティとメソッドをすべて継承します。Tandem サブクラスもデフォルト値が 0 の currentNumberOfPassengers という新しい格納されたプロパティを追加します。
Tandem のインスタンスを作成する場合は、その新しいものと継承されたプロパティのいずれかと作業でき、それが Vehicle から継承する読み取り専用の description プロパティを照会できます。
- let tandem = Tandem()
- tandem.hasBasket = true
- tandem.currentNumberOfPassengers = 2
- tandem.currentSpeed = 22.0
- print("Tandem: \(tandem.description)")
- // Tandem: traveling at 22.0 miles per hour
オーバーライド(上書き)
サブクラスは、インスタンスメソッド、型メソッド、インスタンスプロパティ、型プロパティ、サブスクリプトの独自のカスタム実装を提供でき、そうでなければスーパークラスからの継承を提供できます。これは、オーバーライド(上書き) として知られています。
それ以外の場合継承される特徴をオーバーライドするには、override キーワードを、オーバーライドする定義の前に付けます。そうすることで、オーバーライドを提供する意向と、誤って一致する定義を提供していないことを明確にします。間違ってオーバーライドすると、予期しない動作を引き起こし、そしてコードがコンパイルされた時には、override キーワードなしにオーバーライドした場合はエラーと診断されます。
override キーワードはまた、オーバーライドするクラスのスーパークラス (またはその親の一つ) がオーバーライドのために提供したものと一致する宣言を持っているかをチェックするように Swift コンパイラに求めます。このチェックは、オーバーライドの定義が正しいことを確かめます。
スーパークラスメソッド、プロパティ、サブスクリプトへのアクセス
メソッド、プロパティ、またはサブクラスのサブスクリプトオーバーライドを提供するときは、オーバーライドの一部として、既存のスーパークラスの実装を使用すると便利な場合があります。たとえば、その既存の実装の動作を洗練することができ、または既存の継承された変数に変更された値を格納できます。
これが適切である所には、super の接頭辞を使用してメソッド、プロパティ、またはサブスクリプトのスーパークラスバージョンにアクセスして下さい:
- someMethod() という名前のオーバーライドされたメソッドは、オーバーライドしているメソッドの実装内で super.someMethod() を呼び出すことで someMethod() のスーパークラスバージョンを呼び出すことができます。
- someProperty と言うオーバーライドされたプロパティはオーバーライドしているゲッタまたはセッタの実装内で super.someProperty として someProperty のスーパークラスバージョンにアクセスできます。
- someIndex と言うオーバーライドされたサブスクリプトは、オーバーライドしているサブスクリプトの実装内から super[someIndex] と同じサブスクリプトのスーパークラスバージョンにアクセスできます。
オーバーライドするメソッド
サブクラス内のメソッドの誂えた、または代替の実装を提供するために、継承されたインスタンスまたは型メソッドをオーバーライドできます。
以下の例では、Train と言う Vehicle の新しいサブクラスを定義しており、Vehicle から Train が継承した makeNoise() メソッドをオーバーライドしています。
- class Train: Vehicle {
- override func makeNoise() {
- print("Choo Choo")
- }
- }
Train の新しいインスタンスを作成し、その makeNoise() メソッドを呼び出すと、メソッドの Train サブクラスのバージョンが呼び出されたことがわかります。
- let train = Train()
- train.makeNoise()
- // prints "Choo Choo"
オーバーライドするプロパティ
そのプロパティに独自のカスタムゲッタとセッタを提供して、継承したインスタンスや型プロパティをオーバーライドでき、または基礎となるプロパティ値が変化した時監視するように、プロパティ監視者を追加してプロパティのオーバーライドを有効にします。
プロパティのゲッタとセッタのオーバーライド
継承されたプロパティがソースで、格納されたプロパティとか、計算されたプロパティとして実装されているかどうかには関係なく、全ての 継承されたプロパティをオーバーライドする、カスタムのゲッタを(適切であれば、セッタも) 提供できます。継承されたプロパティの格納された、または計算された性質は、サブクラスによって知られておらず、継承されたプロパティは、特定の名前と型を持っていることを知っているだけです。オーバーライドするプロパティの名前と型を両方とも、オーバーライドが同じ名前と型のスーパークラスのプロパティと一致する事を確認するようにコンパイラができるよう常に宣言しなければなりません。
サブクラスのプロパティのオーバーライドでゲッタとセッタの両方を提供することで、読み書きできるプロパティとして継承された読み取り専用のプロパティを提示できます。ただし、読み取り専用のプロパティを、継承された読み書きできるプロパティとして提示することはできません。
以下の例では、Vehicle のサブクラスである Car と言う新しいクラスを定義しています。Car クラスは gear と言う新しい格納されたプロパティを導入し、そのデフォルトの整数値は 1 です。Car クラスはまた Vehicle から継承した description プロパティをオーバーライドし、現在の gear を含むカスタムの description (説明) を提供します:
- class Car: Vehicle {
- var gear = 1
- override var description: String {
- return super.description + " in gear \(gear)"
- }
- }
description プロパティのオーバーライドは、Vehicle クラスの description プロパティを返す super.description を呼び出して始まります。description の Car クラスのバージョンは、現在の gear についての情報を提供するために、この説明 (description) の最後にいくつかテキストを追加します。
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 インスタンスの currentSpeed プロパティを設定するたびに、プロパティの didSet 監視者は、新しい速度に対するギアを適切に選択し、インスタンスの gear プロパティを設定します。具体的には、プロパティ監視者は、10 で割った新しい currentSpeed 値を、最も近い整数に切り捨て、1 を加えた値のギアを選択します。35.0 の速度は 4 のギアを生成します。
- let automatic = AutomaticCar()
- automatic.currentSpeed = 35.0
- print("AutomaticCar: \(automatic.description)")
- // AutomaticCar: traveling at 35.0 miles per hour in gear 4
オーバーライドの防止
final とマークすることでメソッド、プロパティ、またはサブスクリプトを、オーバーライドされる事から防ぐことができます。メソッド、プロパティ、またはサブスクリプトの前置キーワードの前に final 修飾子を書くことでこれができます。(final var、final func、final class func、そして final subscript のように)
サブクラス内の final メソッド、プロパティ、またはサブスクリプトをオーバーライドしようとしても、コンパイル時エラーとして報告されます。拡張機能内のクラスに追加するメソッド、プロパティ、またはサブスクリプトも拡張機能の定義内で final としてマークできます。
そのクラス定義 (final class) 内で class キーワードの前に final 修飾子を書くことで、全体のクラスを final とマークできます。サブクラスを final クラスにしようとすると、コンパイル時エラーとして報告されます。
前:サブスクリプト 次:初期化
トップへ
トップへ
トップへ
トップへ