Menu
Coddy logo textTech

Mixinの作成

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

ミックスインが何であるかを理解したところで、それらを適切に作成する方法を見ていきましょう。ミックスインは、class の代わりに mixin キーワードを使用して宣言されます。

mixin Logging {
  void log(String message) {
    print('[LOG] $message');
  }
  
  void logError(String error) {
    print('[ERROR] $error');
  }
}

ミックスインは、クラスと同じように、メソッド、プロパティ、さらにはゲッターやセッターを含めることができます。しかし、1つ重要なルールがあります。ミックスインはコンストラクタを持つことができません。ミックスインは直接インスタンス化されるのではなく、「ミックスイン」されることを目的としているため、初期化ロジックは必要ありません。

mixin Timestamped {
  DateTime createdAt = DateTime.now();
  
  String get formattedTime => createdAt.toString();
  
  void printTimestamp() {
    print('Created at: $formattedTime');
  }
}

class Document with Timestamped {
  String title;
  Document(this.title);
}

void main() {
  var doc = Document('Report');
  doc.printTimestamp();  // mixinのメソッドを使用
  print(doc.createdAt);  // mixinのプロパティを使用
}

with を使用してミックスインを適用すると、そのすべてのメンバがクラスの一部になります。クラスはそれらを直接使用でき、そのクラスのインスタンスを持つコードも同様に使用できます。これにより、ミックスインは継承階層の複雑さを伴わずに、再利用可能な機能を追加するためのクリーンな方法となります。

challenge icon

チャレンジ

簡単

メソッド、プロパティ、ゲッターを持つミックスインの作成方法を紹介するメッセージングシステムを構築しましょう。異なるタイプのメッセージにフォーマット機能を追加するミックスインを設計します。

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

  • messaging.dart: ここでミックスインとメッセージクラスを定義します:
    • 以下の内容を含む Formattable ミックスイン:
      • '>>>' で初期化された String prefix プロパティ
      • ' | ' を返すゲッター separator
      • 文字列 [prefix][separator][text] を返すメソッド format(String text)
      • **[text]** を返すメソッド formatBold(String text)
    • Formattable ミックスインを使用する TextMessage クラス。コンストラクタを持つ String sender プロパティを追加します。[sender]: [content] を引数にして format() を呼び出した結果をプリントする send(String content) メソッドを含めます。
    • 同じく Formattable ミックスインを使用する AlertMessage クラス。コンストラクタを持つ String level プロパティを追加します。[[level]] [formatBold(content)] を引数にして format() を呼び出した結果をプリントする alert(String content) メソッドを含めます。
  • main.dart: メッセージングファイルをインポートし、両方のメッセージタイプがミックスインからどのようにフォーマット機能を得るかを実演します:
    • sender が 'Alice'TextMessage を作成します
    • level が 'WARNING'AlertMessage を作成します
    • テキストメッセージに対して send('Hello there!') を呼び出します
    • アラートメッセージに対して alert('System overload') を呼び出します

このミックスインは、ミックスインがデフォルト値を持つプロパティ、値を計算するゲッター、そして互いに呼び出すこともできる複数のメソッドを含めることができることを示しています。両方のメッセージクラスは、with キーワードを使用するだけで、これらすべての機能を得ることができます。

期待される出力:

>>> | Alice: Hello there!
>>> | [WARNING] **System overload**

チートシート

Mixinは、classの代わりにmixinキーワードを使用して宣言されます:

mixin Logging {
  void log(String message) {
    print('[LOG] $message');
  }
  
  void logError(String error) {
    print('[ERROR] $error');
  }
}

Mixinにはメソッド、プロパティ、ゲッター、セッターを含めることができますが、コンストラクタを持つことはできません

mixin Timestamped {
  DateTime createdAt = DateTime.now();
  
  String get formattedTime => createdAt.toString();
  
  void printTimestamp() {
    print('Created at: $formattedTime');
  }
}

withキーワードを使用して、Mixinをクラスに適用します。すべてのMixinメンバーがクラスの一部になります:

class Document with Timestamped {
  String title;
  Document(this.title);
}

void main() {
  var doc = Document('Report');
  doc.printTimestamp();  // Mixinのメソッドを使用
  print(doc.createdAt);  // Mixinのプロパティを使用
}

自分で試してみよう

import 'messaging.dart';

void main() {
  // TODO: 送信者を 'Alice' として TextMessage を作成する
  
  // TODO: レベルを 'WARNING' として AlertMessage を作成する
  
  // TODO: text message に対して send('Hello there!') を呼び出す
  
  // TODO: alert message に対して alert('System overload') を呼び出す
}
quiz icon腕試し

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

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