クラスの継承とメンバーのオーバーライド

クラスの継承 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. オーバーライドのルール

  1. 戻り値型:オーバーライドするメソッドの戻り値型は、親メソッドの型と同一、または親の戻り値型のサブタイプでなければなりません。
  2. 引数の型:オーバーライドするメソッドの引数型は親メソッドと同じ、または親の引数型のスーパータイプとする必要があります(例の intnum。num は int の上位型のため合法)。
  3. 位置指定引数の数:上書き元のメソッドにn個の位置引数がある場合、オーバーライド側もn個の位置引数を定義する必要があります。
  4. 総称型制約:総称メソッドで非総称メソッドを上書きできず、非総称メソッドで総称メソッドを上書きすることもできません。

4. covariantキーワード(型の絞り込みの特殊ケース)

標準ルールでは引数の型を狭めることは許可されません(ダウンキャストにより実行時エラーが発生する可能性があるため);

開発者が実行時エラーが発生しないことを保証できる場合、引数に covariant を付記し、引数型の絞り込みを実装可能です。

演算子 == をオーバーライドする際は、同時に ObjecthashCode 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つの条件(いずれか一方を満たす)
  1. 呼び出し先オブジェクトの静的型が dynamic
  2. 受け取り側の静的型に当該未実装メソッド(抽象メソッド可)が定義されており、受け取り側の実行時型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)

クラスの継承とメンバーのオーバーライド

コメントを残す

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