我非常熟悉接口和抽象类的概念,但对 Mixins的概念不是特别熟悉。
现在,在 Dart 中,每个类 A
都定义了一个隐式接口,可以通过使用 implements
关键字由另一个类 B
实现。没有明确的方法来声明接口,例如,在 Java 中,接口只包含未实现的方法(最终是静态变量)。在 Dart 中,由于接口是由类定义的,所以接口 A
的方法实际上可能已经实现了,但是实现 B
的类仍然需要覆盖这些实现。
我们可以从下面的代码中看到这种情况:
class A {
void m() {
print("method m");
}
}
// LINTER ERROR: Missing concrete implementation of A.m
// Try implementing missing method or make B abstract.
class B implements A {
}
在 Dart 中,混合也是通过普通的类声明定义的..。
... 原则上,每个类都定义了一个可以从中提取出来的 Mixin。但是,在这个方案中,混合只能从没有声明的构造函数的类中提取。这种限制避免了由于需要向继承链上传递构造函数参数而引起的复杂性。
Mixin 基本上是一个既可以定义未实现方法也可以定义已实现方法的类。这是一种向另一个类添加方法而不需要逻辑上使用继承的方法。在 Dart 中,Mixin 被应用到一个超类,该超类通过“普通”继承进行扩展,如下面的示例所示:
class A {
void m() {
print("method m");
}
}
class MyMixin {
void f(){
print("method f");
}
}
class B extends A with MyMixin {
}
在这种情况下,我们应该注意到,B
不必同时实现 A
和 MyMixin
的任何进一步方法。
至少在只支持单亲继承的语言中,应用混合器到类和从类继承之间有着明显的区别,因为在这种情况下,我们可以将许多混合应用到类,但是一个类可以从另一个类继承。
实现接口和从类继承之间也有明显的区别。实现接口的类需要强制实现该接口定义的所有方法。
因此,总的来说,实现接口的概念更多的是关于与实现接口的类建立一个契约,而混合的概念(顾名思义)更多的是关于重用代码(而不是重复使用继承层次结构)。
什么时候使用 Mixin,什么时候在 Dart 中使用接口?在设计软件时,是否有一些经验法则,至少是特殊的循环模式,在这些模式中,最好定义一个 Mixin 并将其应用到超类,而不是让我们的类实现一个接口?我希望在一个既可以使用接口又可以使用混合的上下文环境中使用具体的设计决策示例,但是由于某种原因,一个可以用在另一个上面。