最近お気に入りのresocoderさんの、mixinに関する記事で学習しました。
Mixinが必要になるストーリー
単一継承でうまくいっているパターン
-
Mosquito
クラスが抽象クラスAirborneInsect
を継承(extends
)します。 -
AirborneInsect
クラスはflutter()
、buzz()
というメソッドを持っています。 -
Mosquito
クラスのインスタンスはflutter()
呼び出せます!
単一継承でうまくいかないパターン
- 昆虫だけでなく、鳥も扱うことになりました!
- 抽象クラス
Bird
でflutter()
を持ちます。 -
Bird
を継承したSwallow
でflutter()
を呼び出せます! - しかしこの
flutter()
はAirborneInsect
とBird
で重複しています!
複数の抽象クラスが同じメソッドを持つ重複を解決: mixin
ここで多重継承を可能にするmixin
を使います。
以下のコードではFluttering
クラスを、AirborneInsect
とBird
適用しています。
これでコードの重複がなくなりました!
実際のコード
mixin Fluttering {
void flutter() {
print('fluttering');
}
}
abstract class Insect {
void crawl() {
print('crawling');
}
}
abstract class AirborneInsect extends Insect with Fluttering {
void buzz() {
print('buzzing annoyingly');
}
}
class Mosquito extends AirborneInsect {
void doMosquitoThing() {
crawl();
flutter();
buzz();
print('sucking blood');
}
}
abstract class Bird with Fluttering {
void chirp() {
print('chirp chirp');
}
}
class Swallow extends Bird {
void doSwallowThing() {
chirp();
flutter();
print('eating a mosquito');
}
}
Mixinの使い方
mixin
で定義して、with
句で適用します。
fieldとmethodを継承できます。また、複数mixinを適用できます。
またmixin
は親クラスに適用され、新しい匿名クラスを生成しているようです。
// mixinの定義
mixin M1{
int number = 42;
void say() => print('M1!');
}
mixin M2{
String name = 'M2';
void hello() => print('hello!');
}
// mixinの適用
class C extends Object with M1, M2 {}
main() {
var c = C();
c.say(); // M1!
c.hello(); // hello!
print(c.number); // 42
print(c.name); // M2
}
まずはコードの重複をなくす目的で使ってみると良いと思います。