Menu
Coddy logo textTech

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

CoddyのDartジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 38/110。

メソッドのオーバーライドは、親クラスに既に存在するメソッドに対して、子クラスが独自の定義(実装)を提供したときに発生します。これにより、サブクラスは同じメソッドシグネチャを維持しながら、継承された動作をカスタマイズすることができます。

子クラスで、親クラスと同じ名前および引数を持つメソッドを定義すると、子クラスのバージョンが優先されます。

class Animal {
  String name;
  
  Animal(this.name);
  
  void speak() {
    print('$name makes a sound');
  }
}

class Dog extends Animal {
  Dog(String name) : super(name);
  
  void speak() {
    print('$name barks: Woof!');
  }
}

void main() {
  var animal = Animal('Generic');
  var dog = Dog('Buddy');
  
  animal.speak();  // Generic makes a sound
  dog.speak();     // Buddy barks: Woof!
}

Dog インスタンスで speak() を呼び出すと、Dart は Animal のバージョンではなく、Dog のバージョンを実行します。子クラスが親クラスのメソッドを オーバーライド したことになります。

オーバーライドを super と組み合わせることで、親の振る舞いを置き換えるのではなく、拡張することもできます:

class Cat extends Animal {
  Cat(String name) : super(name);
  
  void speak() {
    super.speak();  // 最初に親のメソッドを呼び出す
    print('$name also purrs');
  }
}

このパターンにより、既存の機能を拡張することができます。重要なルールはシンプルです。子クラスで同じメソッド名とパラメータを定義すると、その子クラスのインスタンスから呼び出された際に、親クラスの実装が上書きされます。

challenge icon

チャレンジ

簡単

子クラスが親クラスのメソッドをオーバーライドして動作をカスタマイズする方法を示す通知システムを構築しましょう。それぞれ独自の方法でメッセージを配信する、異なる通知タイプを作成します。

コードを2つのファイルに整理します:

  • notification.dart: ここで通知の階層を定義します:
    • String titleString message を持つ Notification クラス(親クラス)。両方の値を受け取るコンストラクタと、Notification: [title] - [message] と出力する send() メソッドを含めます。
    • Notification を継承し、String recipient プロパティを追加する EmailNotification クラス。send() メソッドをオーバーライドして、Sending email to [recipient]: [title] - [message] と出力するようにします。
    • Notification を継承し、String deviceId プロパティを追加する PushNotification クラス。send() メソッドをオーバーライドして、まず super を使用して親の send() を呼び出し、次に Pushed to device: [deviceId] を次の行に出力するようにします。
  • main.dart: 通知ファイルをインポートし、メソッドのオーバーライドが動作する様子を確認します:
    • タイトルが 'Alert'、メッセージが 'System update available' のベースとなる Notification を作成します。
    • その send() メソッドを呼び出します。
    • 空行を出力します。
    • タイトルが 'Welcome'、メッセージが 'Thanks for signing up!'、受信者が 'user@example.com'EmailNotification を作成します。
    • その send() メソッドを呼び出します。
    • 空行を出力します。
    • タイトルが 'Reminder'、メッセージが 'Meeting in 10 minutes'、deviceId が 'DEVICE-001'PushNotification を作成します。
    • その send() メソッドを呼び出します。

EmailNotification が親の動作を完全に置き換えるのに対し、PushNotification は最初に super.send() を呼び出すことで動作を拡張している点に注目してください。どちらのアプローチも、ニーズに応じてメソッドをオーバーライドする有効な方法です。

期待される出力:

Notification: Alert - System update available

Sending email to user@example.com: Welcome - Thanks for signing up!

Notification: Reminder - Meeting in 10 minutes
Pushed to device: DEVICE-001

チートシート

メソッドのオーバーライドは、子クラスが親クラスに既に存在するメソッドに対して独自の定義を提供したときに発生します。子クラスのインスタンスで呼び出されると、親クラスのメソッドの代わりに子クラスのメソッドが実行されます。

メソッドをオーバーライドするには、子クラスで同じ名前とパラメータを使用して定義します。

class Animal {
  String name;
  
  Animal(this.name);
  
  void speak() {
    print('$name makes a sound');
  }
}

class Dog extends Animal {
  Dog(String name) : super(name);
  
  void speak() {
    print('$name barks: Woof!');
  }
}

void main() {
  var animal = Animal('Generic');
  var dog = Dog('Buddy');
  
  animal.speak();  // Generic makes a sound
  dog.speak();     // Buddy barks: Woof!
}

super を使用して親クラスのメソッドを呼び出すことで、動作を完全に置き換えるのではなく、拡張することができます。

class Cat extends Animal {
  Cat(String name) : super(name);
  
  void speak() {
    super.speak();  // 最初に親クラスのバージョンを呼び出す
    print('$name also purrs');
  }
}

自分で試してみよう

import 'notification.dart';

void main() {
  // TODO: title が 'Alert'、message が 'System update available' のベースとなる Notification を作成してください
  // その send() メソッドを呼び出します

  // TODO: 空行を出力してください

  // TODO: 以下の内容で EmailNotification を作成してください:
  // - title: 'Welcome'
  // - message: 'Thanks for signing up!'
  // - recipient: 'user@example.com'
  // その send() メソッドを呼び出します

  // TODO: 空行を出力してください

  // TODO: 以下の内容で PushNotification を作成してください:
  // - title: 'Reminder'
  // - message: 'Meeting in 10 minutes'
  // - deviceId: 'DEVICE-001'
  // その send() メソッドを呼び出します
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン