クラスの継承 Extend a class
extendsキーワードを使用し、親クラス(スーパークラス)からサブクラス(派生クラス)を作成します。
superキーワードを使うと、サブクラス内から親クラスのメンバー(メソッド、コンストラクタなど)を呼び出せます。
class Television {
void turnOn() {
...
//親クラスのメソッド内の処理
}
}
// SmartTelevision がサブクラス、Television が親クラス
class SmartTelevision extends Television {
@override
void turnOn() {
super.turnOn(); // 親クラスの turnOn メソッドを呼び出す
//サブクラス固有の処理
...
}
}Code language: Dart (dart)
例として、テレビを親クラス、スマートテレビをサブクラスとすると、スマートテレビはテレビの機能を継承します。
extendsには別の利用場面があります。総称型の章で登場するパラメータ化型に関する記述です。
実例
class Television {
void turnOn() {
print("テレビに通電、基本映像を出力");
}
}
// SmartTelevision がサブクラス、Television が親クラス
class SmartTelevision extends Television {
@override
void turnOn() {
super.turnOn(); // 親クラス turnOn メソッド呼び出し
//サブクラス固有の処理
print("スマートテレビ:ネットワークモジュール起動、スマートシステムホーム画面を読み込み");
}
}
void main() {
// 通常テレビのインスタンス
Television normalTv = Television();
print("===== 通常テレビ起動 =====");
normalTv.turnOn();
// スマートテレビのインスタンス
SmartTelevision smartTv = SmartTelevision();
print("\n===== スマートテレビ起動 =====");
smartTv.turnOn();
}Code language: Dart (dart)
実行結果
D:\dartdemo\firstdart>dart run
Building package executable... (1.4s)
Built firstdart:firstdart.
===== 通常テレビ起動 =====
テレビに通電、基本映像を出力
===== スマートテレビ起動 =====
テレビに通電、基本映像を出力
メンバーのオーバーライド Overriding members
1. オーバーライド可能な要素
サブクラスがオーバーライドできるもの:インスタンスメソッド(演算子を含む)、getter、setter。
2. @overrideアノテーション
役割:対象のメソッドが親クラスのメンバーを明示的に上書きしていることを宣言し、コンパイラによる検証を有効にします。
class Television {
set contrast(int value) {}
}
class SmartTelevision extends Television {
@override //コンパイラに、サブクラスで親メソッドを上書きすることを通知
set contrast(num value) {}
}
Code language: JavaScript (javascript)
3. オーバーライドのルール
- 戻り値型:オーバーライドするメソッドの戻り値型は、親メソッドの型と同一、または親の戻り値型のサブタイプでなければなりません。
- 引数の型:オーバーライドするメソッドの引数型は親メソッドと同じ、または親の引数型のスーパータイプとする必要があります(例の
int→num。num は int の上位型のため合法)。 - 位置指定引数の数:上書き元のメソッドにn個の位置引数がある場合、オーバーライド側もn個の位置引数を定義する必要があります。
- 総称型制約:総称メソッドで非総称メソッドを上書きできず、非総称メソッドで総称メソッドを上書きすることもできません。
4. covariantキーワード(型の絞り込みの特殊ケース)
標準ルールでは引数の型を狭めることは許可されません(ダウンキャストにより実行時エラーが発生する可能性があるため);
開発者が実行時エラーが発生しないことを保証できる場合、引数に covariant を付記し、引数型の絞り込みを実装可能です。
演算子 == をオーバーライドする際は、同時に Object の hashCode getter を必ず上書きしてください。
noSuchMethod ()
1. 役割
存在しないインスタンスメソッド / インスタンス変数を呼び出そうとした場合、noSuchMethod() をオーバーライドして呼び出しを捕捉し、独自の処理を記述できます。
オーバーライドしない場合、存在しないメンバーへアクセスすると NoSuchMethodError が直接スローされます。
class A {
@override
void noSuchMethod(Invocation invocation) {
print('You tried to use a non-existent member: ${invocation.memberName}');
}
}
Code language: JavaScript (javascript)
Invocationオブジェクト:呼び出し情報(メンバー名、引数など)を保持
2. 未実装メソッドの呼び出しが有効になる2つの条件(いずれか一方を満たす)
- 呼び出し先オブジェクトの静的型が
dynamic; - 受け取り側の静的型に当該未実装メソッド(抽象メソッド可)が定義されており、受け取り側の実行時型が
Object標準実装とは異なるnoSuchMethod()を持つこと。
例
class A {
@override
void noSuchMethod(Invocation invocation) {
print('You tried to use a non-existent member: ${invocation.memberName}');
// 引数や呼び出し種別を出力し、詳細情報を表示
print('呼び出し引数:${invocation.arguments}');
print('呼び出し型:${invocation.runtimeType}');
}
}
void main() {
A obj = A();
// 存在しないメソッド呼び出し、noSuchMethod起動
obj.hello("test", 123);
// 存在しないプロパティにアクセス
obj.unknownValue;
}Code language: Dart (dart)
D:\dartdemo\firstdart>dart run
Building package executable...
Failed to build firstdart:firstdart:
bin/firstdart.dart:6:30: Error: The getter 'arguments' isn't defined for the type 'Invocation'.
- 'Invocation' is from 'dart:core'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'arguments'.
print('cal:${invocation.arguments}');
^^^^^^^^^
bin/firstdart.dart:14:7: Error: The method 'hello' isn't defined for the type 'A'.
- 'A' is from 'bin/firstdart.dart'.
Try correcting the name to the name of an existing method, or defining a method named 'hello'.
obj.hello("test", 123);
^^^^^
bin/firstdart.dart:16:7: Error: The getter 'unknownValue' isn't defined for the type 'A'.
- 'A' is from 'bin/firstdart.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'unknownValue'.
obj.unknownValue;Code language: PHP (php)
クラスの継承とメンバーのオーバーライド
Previous: Method(メソッド)
Next: Mixins