Menu
Coddy logo textTech

Mixin入門

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

Dartでは1つのクラスしか継承(extend)できず、複数のインターフェースを実装(implement)することはできますが、すべてのコードを自分で書かなければならないことを学びました。しかし、関連のない複数のクラス間で実際のコードの実装を共有したい場合はどうすればよいでしょうか?そこで登場するのがミックスイン(mixins)です。

ミックスイン(mixin)は、複数のクラス階層でコードを再利用するための手法です。継承を使用せずに、任意のクラスに「ミックスイン」して新しい機能を提供できる、メソッドとプロパティの束だと考えてください。

mixin Swimming {
  void swim() {
    print('Swimming through the water');
  }
}

class Duck with Swimming {
  void quack() {
    print('Quack!');
  }
}

class Fish with Swimming {
  void blowBubbles() {
    print('Blub blub');
  }
}

void main() {
  var duck = Duck();
  duck.quack();
  duck.swim();  // mixinから
  
  var fish = Fish();
  fish.swim();  // 同じ実装、異なるクラス
}

withキーワードに注目してください。これはクラスにミックスインを適用する方法です。implementsとは異なり、メソッドを自分で書く必要はありません。ミックスインが実際のコードを提供し、クラスはその機能を自動的に獲得します。

ミックスインは現実的な問題を解決します:DuckFish は継承関係にはありませんが、両方とも泳ぐ振る舞いを必要としています。ミックスインを使えば、コードを一度書くだけで、必要な場所ならどこでも共有できます。

challenge icon

チャレンジ

簡単

ミックスインを使用して、継承関係のないクラス間で動作を共有する方法を示す楽器システムを構築しましょう。チューニング機能を提供するミックスインを作成し、それを継承関係のない異なる楽器に適用します。

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

  • instruments.dart: ここでミックスインと楽器クラスを定義します:
    • Tuning the instrument... と出力する tune() メソッドと、Tuning is perfect! と出力する checkTuning() メソッドを持つ Tunable ミックスイン。
    • Tunable ミックスインを使用する Guitar クラス。コンストラクタを持つ String brand プロパティを追加します。[brand] guitar strumming chords と出力する strum() メソッドを含めます。
    • 同じく Tunable ミックスインを使用する Piano クラス。コンストラクタを持つ int keys プロパティを追加します。Playing [keys]-key piano と出力する play() メソッドを含めます。
  • main.dart: 楽器ファイルをインポートし、継承関係のない両方の楽器が同じミックスインからどのようにチューニング機能を得るかを実演します:
    • ブランドが 'Fender'Guitar を作成します。
    • 88 鍵の Piano を作成します。
    • ギターの場合:tune() を呼び出し、次に strum()、最後に checkTuning() を呼び出します。
    • 空行を出力します。
    • ピアノの場合:tune() を呼び出し、次に play()、最後に checkTuning() を呼び出します。

GuitarPiano は継承関係のない完全に異なる楽器ですが、どちらも Tunable ミックスインから全く同じチューニングメソッドを取得していることに注目してください。チューニングのコードを一度書くだけで、with キーワードを使用して両方のクラスで利用できます。

期待される出力:

Tuning the instrument...
Fender guitar strumming chords
Tuning is perfect!

Tuning the instrument...
Playing 88-key piano
Tuning is perfect!

チートシート

ミックスインは、継承を使用せずに、関連のない複数のクラス間でコードを再利用する方法です。これは、任意のクラスに「ミックスイン(混ぜ込む)」ことができるメソッドとプロパティのセットです。

mixinキーワードを使用してミックスインを定義します:

mixin Swimming {
  void swim() {
    print('Swimming through the water');
  }
}

withキーワードを使用して、クラスにミックスインを適用します:

class Duck with Swimming {
  void quack() {
    print('Quack!');
  }
}

class Fish with Swimming {
  void blowBubbles() {
    print('Blub blub');
  }
}

implementsとは異なり、メソッドの実装を自分自身で書く必要はありません。ミックスインが実際のコードを提供し、クラスはその機能を自動的に獲得します。

DuckFishは、継承関係になくても、両方ともswim()メソッドを使用できるようになります:

var duck = Duck();
duck.swim();  // ミックスインから

var fish = Fish();
fish.swim();  // 同じ実装、異なるクラス

自分で試してみよう

import 'instruments.dart';

void main() {
  // TODO: ブランド 'Fender' で Guitar を作成する
  
  // TODO: 88 鍵の Piano を作成する
  
  // TODO: guitar に対して tune()、次に strum()、その次に checkTuning() を呼び出す
  
  // TODO: 空行を出力する
  
  // TODO: piano に対して tune()、次に play()、その次に checkTuning() を呼び出す
}
quiz icon腕試し

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

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