Menu
Coddy logo textTech

インターフェースによるポリモーフィズム

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

前のレッスンでは、継承によるポリモーフィズム、つまり親クラスの型を使用して子オブジェクトを操作する方法について学びました。しかし、ポリモーフィズムはインターフェースを通じても機能し、このアプローチは多くの場合、より柔軟です。

クラスが同じインターフェースを実装している場合、継承関係がなくても、それらをポリモーフィックに扱うことができます:

abstract class Printable {
  void printDetails();
}

class Invoice implements Printable {
  @override
  void printDetails() => print('Invoice #1234');
}

class Report implements Printable {
  @override
  void printDetails() => print('Monthly Report');
}

class Receipt implements Printable {
  @override
  void printDetails() => print('Receipt for purchase');
}

void printAll(List<Printable> items) {
  for (var item in items) {
    item.printDetails();
  }
}

void main() {
  var documents = [Invoice(), Report(), Receipt()];
  printAll(documents);
}

InvoiceReport、および Receipt は完全に無関係なクラスであり、親クラスを共有していません。しかし、これらはすべて Printable を実装しているため、同じリストに格納し、それぞれに対して printDetails() を呼び出すことができます。

これは、継承階層を強制することなく振る舞いの契約(behavior contracts)を定義できるため、強力です。何を継承しているかに関わらず、どのクラスでもインターフェースを実装できます。既存のコードを修正することなく、新しい印刷可能な型を追加できるため、コードのモジュール性が高まります。単にインターフェースを実装するだけです。

challenge icon

チャレンジ

簡単

インターフェースを通じてポリモーフィズムを実証するメディアプレーヤーシステムを構築しましょう。「再生可能」であることの意味を定義するインターフェースを作成し、継承関係のない複数の無関係なメディアタイプにこのコントラクトを実装させます。これにより、それらを一律に扱うことができるようになります。

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

  • media.dart: ここでインターフェースとメディアクラスを定義します:
    • 2つの抽象メソッド play()String getMediaType() を持つ抽象クラス Playable
    • Playable を実装する Song クラス。String titleString artist を持つ必要があります。その play() メソッドは Playing song: [title] by [artist] を出力し、getMediaType()'Audio' を返します。
    • Playable を実装する Video クラス。String titleint duration(分単位)を持つ必要があります。その play() メソッドは Playing video: [title] ([duration] min) を出力し、getMediaType()'Video' を返します。
    • Playable を実装する Podcast クラス。String titleint episode を持つ必要があります。その play() メソッドは Playing podcast: [title] - Episode [episode] を出力し、getMediaType()'Podcast' を返します。
    また、リストを反復処理し、各アイテムに対して [Media Type]: を出力した後にそのアイテムの play() を呼び出す関数 playAll(List<Playable> playlist) を作成します。
  • main.dart: メディアファイルをインポートし、インターフェースベースのポリモーフィズムを実証します:
    • タイトルが 'Imagine' でアーティストが 'John Lennon'Song、タイトルが 'Dart Tutorial' で時間が 15Video、タイトルが 'Tech Talk' でエピソードが 42Podcast を含む List<Playable> を作成します。
    • このリストを playAll() に渡します。

SongVideoPodcast が親クラスを共有していないこと(完全に無関係な型であること)に注目してください。しかし、それらはすべて Playable を実装しているため、同じリストに格納し、インターフェースを通じて一律に扱うことができます。

期待される出力:

Audio:
Playing song: Imagine by John Lennon
Video:
Playing video: Dart Tutorial (15 min)
Podcast:
Playing podcast: Tech Talk - Episode 42

自分で試してみよう

import 'media.dart';

void main() {
  // TODO: 以下を含む List<Playable> を作成してください:
  // - タイトルが 'Imagine'、アーティストが 'John Lennon' の Song
  // - タイトルが 'Dart Tutorial'、長さが 15 の Video
  // - タイトルが 'Tech Talk'、エピソードが 42 の Podcast
  
  // TODO: そのリストを playAll() に渡してください
}
quiz icon腕試し

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

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