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)」の概念がどのように機能するかを詳しく見ていきます。
チャレンジ
簡単Dartにおける implements キーワードの仕組みを理解するために、メディアプレーヤーシステムを構築しましょう。インターフェースとして機能するクラスを作成し、それらを複数の機能を組み合わせた単一のデバイスに実装します。
コードは2つのファイルに分けて構成します:
media.dart: ここでインターフェースクラスと実装クラスを定義します:AudioPlayerクラス:Playing audio: [track]と出力するplayAudio(String track)メソッドを持ちます。VideoPlayerクラス:Playing video: [title]と出力するplayVideo(String title)メソッドを持ちます。SmartTVクラス:AudioPlayerとVideoPlayerの両方を実装(implements)します。implementsはコードを継承しないため、両方のメソッドに対して独自の実装を提供する必要があります。SmartTVは、オーディオに対してはSmartTV audio: [track]、ビデオに対してはSmartTV video: [title]と出力するようにしてください。
main.dart: メディアファイルをインポートし、単一のクラスが複数のインターフェースをどのように実装できるかを示します:SmartTVのインスタンスを作成します。playAudio('Jazz Collection')を呼び出します。playVideo('Nature Documentary')を呼び出します。
SmartTV が両方のインターフェースのすべてのメソッドに対して独自の実装を提供しなければならない点に注目してください。AudioPlayer や VideoPlayer から元の実装を継承することはありません。これが implements と extends の主な違いです。
期待される出力:
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') を呼び出す
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4Null Safety
Null Safety 入門Nullable と Non-Nullable? 演算子と ! 演算子late キーワードと Null SafetyNull-Aware 演算子クラスにおける Null Safetyまとめ:ユーザープロフィールシステム10コレクションとジェネリクス
List, Set, Map の概要型安全なコレクションジェネリッククラスジェネリックメソッドジェネリクスの制約Iterable と Iteratorまとめ:ジェネリックなストレージ