開発者ドキュメント

DartのMixinsの紹介

オブジェクト指向プログラミング(OOP)を使用する最も良い理由のいくつかは、コードをクリーンでドライに保つのに役立つテクニックです。 コードを別々のクラスで再利用できるようにするためのDartの戦略のいくつかを探求します。

問題

2つのクリーチャークラスがあり、それぞれが独自の動作セットを持っていると想像してください。 明らかな解決策は、必要に応じて各クラスのメソッドの概要を直接示すことですが、多くのクラスは完全に一意ではなく、互いに多くの共通点を共有します。 これらのクラスを最も再利用可能な方法で作成するための最も効率的な構造を見つけたいのは明らかです。

私たちの動物は、実行できるいくつかの特定のアクションと、それらから構成されるより大きな行動を持ちます。 ご覧のとおり、食事は異なる場合がありますが、方法はほとんど同じであり、理想的にはより再利用可能なものに分割する必要があります。

main.dart
class Alligator {
  void swim() => print('Swimming');
  void bite() => print('Chomp');
  void crawl() => print('Crawling');
  void hunt() {
    print('Alligator -------');
    swim();
    crawl();
    bite();
    print('Eat Fish');
  }
}

class Crocodile {
  void swim() => print('Swimming');
  void bite() => print('Chomp');
  void crawl() => print('Crawling');
  void hunt() {
    print('Crocodile -------');
    swim();
    crawl();
    bite();
    print('Eat Zebra');
  }
}

main() {
  Crocodile().hunt();
  Alligator().hunt();
}

// Output should be 
// Crocodile -------
// Swimming
// Crawling
// Chomp
// Eat Zebra
// Alligator -------
// Swimming
// Crawling
// Chomp
// Eat Fish

拡張機能

私たちが持っている最も一般的なオプションは拡張機能です。この拡張機能では、あるクラスのプロパティとメソッドを取得して、別のクラスで使用できるようにすることができます。 Reptileを独自のインスタンスで使用しないため、抽象クラスとして設定して、初期化できず、拡張するだけで済みます。

main.dart
abstract class Reptile {
  void bite() => print('Chomp');
  void swim() => print('Swimming');
  void crawl() => print('Crawling');
  void hunt() {
    print('${this.runtimeType} -------');
    swim();
    crawl();
    bite();
  }
}

class Alligator extends Reptile {
    // Alligator Specific stuff...
}

class Crocodile extends Reptile {
    // Crocodile Specific stuff...
}

main() {
  Crocodile().hunt('Zebra');
  Alligator().hunt('Fish');
}

Mixins

これは現在の例では良いことですが、動物を追加すると、これらの方法の多くが爬虫類だけのものではないことがすぐに明らかになります。 Reptileを拡張するだけでなく、swimメソッドを使用してFishクラスを作成したい場合は、extendsクラスごとに1つ。 ミックスインを使用して、より普遍的な動作をより小さく、より再利用可能なコンポーネントに分割し、必要なクラスに追加することができます。

メソッドを格納するためにmixinタイプを使用し、それを含めるすべてのクラスでwithキーワードを使用する必要があります。 extendsとは異なり、クラスに必要な数のミックスインを追加できます。

main.dart
mixin Swim {
  void swim() => print('Swimming');
}

mixin Bite {
  void bite() => print('Chomp');
}

mixin Crawl {
  void crawl() => print('Crawling');
}

abstract class Reptile with Swim, Crawl, Bite {
  void hunt(food) {
    print('${this.runtimeType} -------');
    swim();
    crawl();
    bite();
    print('Eat $food');
  }
}

class Alligator extends Reptile {
  // Alligator Specific stuff...
}

class Crocodile extends Reptile {
  // Crocodile Specific stuff...
}

class Fish with Swim, Bite {
  void feed() {
    print('Fish --------');
    swim();
    bite();
  }
}

main() {
  Crocodile().hunt('Zebra');
  Alligator().hunt('Fish');
  Fish().feed();
}

の上

私たちが持っている最後のトリックは、私が逆拡張として考えたいことをする能力です。 クラスのメソッドを利用するミックスインを作成し、それを各サブクラスで使用できます。

Huntを独自のミックスインに分割したい場合は、onキーワードを使用して、Reptileクラスでのみ使用されることを通知できます。 SwimCrawlBiteミックスインなどのすべての機能にアクセスできます。

この構成は、最初の構成とまったく同じ出力になるはずです。

main.dart
mixin Hunt on Reptile {
  void hunt(food) {
    print('${this.runtimeType} -------');
    swim();
    crawl();
    bite();
    print('Eat $food');
  }
}

abstract class Reptile with Swim, Crawl, Bite {}

class Alligator extends Reptile with Hunt {
  // Alligator Specific stuff...
}

class Crocodile extends Reptile with Hunt {
  // Crocodile Specific stuff...
}

結論

Flutterの人気が高まるにつれ、Dartプログラミング言語の基本を十分に理解することをお勧めします。 うまくいけば、これがDartクラスの再利用に関する謎のいくつかを明らかにするための有益な紹介でした。

モバイルバージョンを終了