混入是一种可以在多个类层次结构中重复使用代码的定义方式。它们旨在大量提供成员实现。

要使用混入,请使用 with 关键字,后跟一个或多个混入名称。以下示例显示了使用混入的两个类

dart
class Musician extends Performer with Musical {
  // ···
}

class Maestro extends Person with Musical, Aggressive, Demented {
  Maestro(String maestroName) {
    name = maestroName;
    canConduct = true;
  }
}

要定义混合,请使用 mixin 声明。在极少数情况下,您需要同时定义混合类,您可以使用 mixin class 声明

混合和混合类不能有 extends 子句,并且不能声明任何生成构造函数。

例如

dart
mixin Musical {
  bool canPlayPiano = false;
  bool canCompose = false;
  bool canConduct = false;

  void entertainMe() {
    if (canPlayPiano) {
      print('Playing piano');
    } else if (canConduct) {
      print('Waving hands');
    } else {
      print('Humming to self');
    }
  }
}

有时您可能希望限制可以使用混合的类型。例如,混合可能依赖于能够调用混合未定义的方法。如下例所示,您可以使用 on 关键字指定必需的超类来限制混合的使用

dart
class Musician {
  // ...
}

mixin MusicalPerformer on Musician {
  // ...
}
class SingerDancer extends Musician with MusicalPerformer {
  // ...
}

在前面的代码中,只有扩展或实现 Musician 类的类才能使用混合 MusicalPerformer。因为 SingerDancer 扩展了 Musician,所以 SingerDancer 可以混合 MusicalPerformer

classmixin 还是 mixin class

#

mixin 声明定义一个混合。class 声明定义一个 mixin class 声明定义一个类,该类可以用作常规类和混合,名称和类型相同。

适用于类或混合的任何限制也适用于混合类

  • 混合不能有 extendswith 子句,所以 mixin class 也不行。
  • 类不能有 on 子句,所以 mixin class 也不行。

抽象混合类

#

您可以实现类似于混合类 on 指令的行为。使混合类成为 abstract 并定义其行为所依赖的抽象方法

dart
abstract mixin class Musician {
  // No 'on' clause, but an abstract method that other types must define if 
  // they want to use (mix in or extend) Musician: 
  void playInstrument(String instrumentName);

  void playPiano() {
    playInstrument('Piano');
  }
  void playFlute() {
    playInstrument('Flute');
  }
}

class Virtuoso with Musician { // Use Musician as a mixin
  void playInstrument(String instrumentName) {
    print('Plays the $instrumentName beautifully');
  }  
} 

class Novice extends Musician { // Use Musician as a class
  void playInstrument(String instrumentName) {
    print('Plays the $instrumentName poorly');
  }  
}

通过将 Musician 混合声明为抽象,您可以强制任何使用它的类型定义其行为所依赖的抽象方法。

这类似于 on 指令如何通过指定该接口的超类来确保混合可以访问它所依赖的任何接口。