Menu
Coddy logo textTech

Dart におけるインターフェース

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

専用の interface キーワードを持つ多くの言語とは異なり、Dartは異なるアプローチを取ります。Dartでは、すべてのクラスが自動的にインターフェースを定義します。このインターフェースは、そのクラスが宣言するすべての公開メンバー(メソッドとプロパティ)で構成されています。

クラスが実装を継承せずに特定の機能を提供することを約束したい場合は、implementsキーワードを使用します:

class Printer {
  void printDocument(String content) {
    print('Printing: $content');
  }
}

class Scanner {
  void scan() {
    print('Scanning document');
  }
}

// MultiFunctionDeviceは両方のクラスのすべてのメソッドを実装する必要があります
class MultiFunctionDevice implements Printer, Scanner {
  @override
  void printDocument(String content) {
    print('MFD printing: $content');
  }
  
  @override
  void scan() {
    print('MFD scanning');
  }
}

extends との主な違いは、implements はコードを一切継承しないことです。インターフェースで定義されているすべてのメソッドとプロパティに対して、独自の型実装を提供する必要があります。これは契約です。クラスがこれらの機能を持つことを約束しますが、それらが具体的にどのように動作するかはあなたが決定します。

このアプローチはDartに柔軟性をもたらします。実装のないインターフェースを定義したい場合には抽象クラス(abstract classes)を使用でき、理にかなっている場合には通常のクラスをインターフェースとして使用することもできます。次のレッスンでは、この「暗黙的インターフェース(implicit interface)」の概念がどのように機能するかを詳しく見ていきます。

challenge icon

チャレンジ

簡単

Dartにおける implements キーワードの仕組みを理解するために、メディアプレーヤーシステムを構築しましょう。インターフェースとして機能するクラスを作成し、それらを複数の機能を組み合わせた単一のデバイスに実装します。

コードは2つのファイルに分けて構成します:

  • media.dart: ここでインターフェースクラスと実装クラスを定義します:
    • AudioPlayer クラス:Playing audio: [track] と出力する playAudio(String track) メソッドを持ちます。
    • VideoPlayer クラス:Playing video: [title] と出力する playVideo(String title) メソッドを持ちます。
    • SmartTV クラス:AudioPlayerVideoPlayer の両方を実装(implements)します。implements はコードを継承しないため、両方のメソッドに対して独自の実装を提供する必要があります。SmartTV は、オーディオに対しては SmartTV audio: [track]、ビデオに対しては SmartTV video: [title] と出力するようにしてください。
  • main.dart: メディアファイルをインポートし、単一のクラスが複数のインターフェースをどのように実装できるかを示します:
    • SmartTV のインスタンスを作成します。
    • playAudio('Jazz Collection') を呼び出します。
    • playVideo('Nature Documentary') を呼び出します。

SmartTV が両方のインターフェースのすべてのメソッドに対して独自の実装を提供しなければならない点に注目してください。AudioPlayerVideoPlayer から元の実装を継承することはありません。これが implementsextends の主な違いです。

期待される出力:

SmartTV audio: Jazz Collection
SmartTV video: Nature Documentary

チートシート

Dartでは、すべてのクラスがそのすべての公開メンバーで構成されるインターフェースを自動的に定義します。コードを継承せずにインターフェースを実装するには、implementsキーワードを使用します。

class Printer {
  void printDocument(String content) {
    print('Printing: $content');
  }
}

class Scanner {
  void scan() {
    print('Scanning document');
  }
}

// 両方のクラスのすべてのメソッドを実装する必要があります
class MultiFunctionDevice implements Printer, Scanner {
  @override
  void printDocument(String content) {
    print('MFD printing: $content');
  }
  
  @override
  void scan() {
    print('MFD scanning');
  }
}

extendsとの主な違い:

  • implementsはコードの実装を一切継承しません
  • すべてのメソッドとプロパティに対して、独自の実装を提供する必要があります
  • 1つのクラスで複数のインターフェースを実装できます
  • これは、クラスがこれらの機能を持つことを約束する契約です

自分で試してみよう

import 'media.dart';

void main() {
  // TODO: SmartTV インスタンスを作成する
  
  // TODO: playAudio('Jazz Collection') を呼び出す
  
  // TODO: playVideo('Nature Documentary') を呼び出す
  
}
quiz icon腕試し

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

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