super キーワード
CoddyのDartジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 37/110。
superキーワードは、子クラスからその親クラスに直接アクセスできるようにします。すでにコンストラクタの中でsuper(name)として使用されているのを見たことがあると思いますが、他のコンテキストでも便利です。
親のコンストラクタを呼び出す必要がある場合、super は継承チェーンに沿って引数を渡します:
class Vehicle {
String brand;
int year;
Vehicle(this.brand, this.year);
}
class Car extends Vehicle {
int doors;
Car(String brand, int year, this.doors) : super(brand, year);
}superキーワードを使用すると、子クラス内から親のメソッドやプロパティにアクセスすることもできます。これは、親の振る舞いを自分自身の振る舞いと併せて使用したい場合に特に便利です。
class Animal {
String name;
Animal(this.name);
void makeSound() {
print('$name makes a sound');
}
}
class Cat extends Animal {
Cat(String name) : super(name);
void makeSound() {
super.makeSound(); // 最初に親のメソッドを呼び出す
print('$name says meow!');
}
}super.makeSound() を呼び出すと、親クラスのバージョンのメソッドを明示的に呼び出すことになります。super がないと、makeSound() の呼び出しは現在のクラスのメソッドを参照することになり、潜在的に無限再帰を引き起こす可能性があります。
super を、「親のバージョンを使って」と言っているものだと考えてください。それがコンストラクタ、メソッド、プロパティのいずれであっても同様です。
チャレンジ
簡単super キーワードを使用して、子クラスが親クラスの振る舞いにアクセスし、それを拡張する方法を示すメッセージングシステムを構築しましょう。基本となるメッセージクラスを基に、異なるメッセージタイプの階層を作成します。
コードを2つのファイルに整理します:
message.dart: ここでメッセージクラスを定義します:String senderとString contentを持つMessageクラス(親クラス)。これら2つの値を受け取るコンストラクタと、From [sender]: [content]と出力するdisplay()メソッドを含めます。Messageを継承するUrgentMessageクラス。追加のString priorityプロパティを持たせる必要があります。コンストラクタは sender、content、priority を受け取り、最初の2つをsuperを使用して親クラスに渡します。display()メソッドをオーバーライドし、最初にsuper.display()を使用して親クラスのバージョンを呼び出し、次にPriority: [priority]を次の行に出力するようにします。
main.dart: メッセージファイルをインポートし、コンストラクタとメソッドの両方でsuperがどのように機能するかを示します:'Alice'からの内容'Hello there!'の通常のMessageを作成します。- その
display()メソッドを呼び出します。 - 区切りのために空行を出力します。
'Bob'からの内容'Server is down!'、優先度'HIGH'のUrgentMessageを作成します。- その
display()メソッドを呼び出します。
UrgentMessage が super を2つの方法で使用していることに注目してください。1つはコンストラクタで親にデータを渡すため、もう1つはオーバーライドされたメソッドで独自の出力を追加する前に親の出力を取り込むためです。
期待される出力:
From Alice: Hello there!
From Bob: Server is down!
Priority: HIGHチートシート
super キーワードは、子クラス内から親クラスへのアクセスを提供します。
子クラスのコンストラクタで super() を使用して、親のコンストラクタに引数を渡します。
class Vehicle {
String brand;
int year;
Vehicle(this.brand, this.year);
}
class Car extends Vehicle {
int doors;
Car(String brand, int year, this.doors) : super(brand, year);
}オーバーライドされたメソッド内から親のメソッドを呼び出すには、super を使用します。
class Animal {
String name;
Animal(this.name);
void makeSound() {
print('$name makes a sound');
}
}
class Cat extends Animal {
Cat(String name) : super(name);
void makeSound() {
super.makeSound(); // 親のメソッドを最初に呼び出す
print('$name says meow!');
}
}super を使用せずにメソッド名を直接呼び出すと、現在のクラスのバージョンが参照されるため、オーバーライドされたメソッド内で無限再帰が発生する可能性があります。
自分で試してみよう
import 'message.dart';
void main() {
// TODO: 'Alice' から内容が 'Hello there!' の通常の Message を作成する
// TODO: message に対して display() メソッドを呼び出す
// TODO: 区切りのために空行を出力する
// TODO: 'Bob' から内容が 'Server is down!' で優先度が 'HIGH' の UrgentMessage を作成する
// TODO: urgent message に対して display() メソッドを呼び出す
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4Null Safety
Null Safety 入門Nullable と Non-Nullable? 演算子と ! 演算子late キーワードと Null SafetyNull-Aware 演算子クラスにおける Null Safetyまとめ:ユーザープロフィールシステム10コレクションとジェネリクス
List, Set, Map の概要型安全なコレクションジェネリッククラスジェネリックメソッドジェネリクスの制約Iterable と Iteratorまとめ:ジェネリックなストレージ