本文由 简悦SimpRead 转码,原文地址 medium.com
在面向对象的编程语言中,Mixin是一个包含方法的类,供其他c......。
把Class混合到一起
我是一个拥有大量Java和一般编程经验的Android开发者。今年Flutter从其测试版发布开始就获得了大量的曝光,吸引了许多来自Android、IOS甚至是网络的开发者。
在Flutter 1.0发布后,它几乎勾起了所有移动开发者的好奇心。当我第一次看到它时,它似乎非常有趣,所以我决定给它一个机会。
当我意识到我必须学习一种新的编程语言才能开始使用Flutter时,我几乎打算跳过尝试它。学习一门新的编程语言总是一个耗时的过程。也就是说,当我看了Dart网站上的一些例子后,一切都改变了。Dart给人的感觉就像家一样。它是一种非常简洁易懂的语言,特别是如果你有Java、JavaScript、C#或任何其他_面向对象的编程语言的编程背景。你将在几个小时内启动并运行Dart程序。
从我使用Dart的时间来看,我觉得有一个话题有点棘手,那就是混合器。对于Java开发者来说,这是一个完全陌生的概念,因为Java不支持多重继承或混合体。Java试图通过使用接口来弥补这一缺陷,但这并不像 mixins 那样有用或灵活。
所以,让我们先试着了解一下什么是 mixins ?
💫 mixin到底是什么?
我认为混合体的最简明定义是由维基百科提供的。
"在面向对象的编程语言中,一个 Mixin 是一个包含供其他类使用的方法的类,而不必是这些其他类的父类。"
换句话说,混合体是普通的类,我们可以借用其中的方法(或变量)而不需要扩展该类。在dart中,我们可以通过使用关键字with来做到这一点。如果你想用类B作为类A的混合体,那么:
class B { //B is not allowed to extend any other class other than object
method(){
....
}
}
class A with B {
....
......
}
void main() {
A a = A();
a.method(); //we got the method without inheriting B
}
代码class A with B等同于class A extends Object with B。现在,类只能作为 mixins 使用,一旦它们只扩展object。扩展其他类的类不能作为一个 mixin 使用。然而,这在未来可能会改变,因为Dart在不断发展,而且已经有一个实验性的功能,允许我们使用 mixins 扩展Object以外的类。也许在阅读这篇文章的时候,mixins的行为方式可能会有一些小的变化。所以请随时关注mixin specifications。
尽管我们不能使用扩展除 "Object "以外的类的混集类,但我们可以扩展或实现使用混集类的基类(本例中的 "A "类)。
class B { //B is not allowed to extend any other class other than object
method(){
....
}
}
class C {
...
...
}
class A extends C with B { . //we can extends of implement class A
....
......
}
void main() {
A a = A();
assert(a is B); // a is b = true
assert(a is C); // a is c = true
a.method(); //we got the method without inheriting B
}
混合类使编程语言能够模仿并受益于多重继承和代码重用等特性,同时也减少了遇到诸如致命的死亡之钻(DDD)等问题的风险。
有些人把mixins描述为一个带有实现的接口。
什么是多重继承中的死亡之钻(DDD)?
假设我们有一个叫做Performer的抽象类。
abstract class Performer {
void perform();
}
现在我们将创建两个具体的类Dancer和Singer,它们扩展了Performer。
class Dancer extends Performer {
void perform() {
print('Dance Dance Dance ');
}
}
class Singer extends Performer {
void perform() {
print('lalaaa..laaalaaa....laaaaa');
}
}
扩展Performer是唯一能让我跳舞和唱歌的方法。
现在假设dart支持多重继承,一个叫做Musician的类扩展了Dancer和Singer这两个类。
注意:Dart只支持单继承,我在这里只是假设,如果Dart像C++一样支持多继承会怎样:
你能猜到哪个perform()方法会在Musician类中被调用吗?
class Musician extends Dancer,Singer {
void showTime() {
perform();
}
}
感到困惑?这就是编译器在我们试图运行这段代码时的感觉。因为我们没有实际的方法来决定哪个是正确的方法要调用。这种情况被称为致命的死亡之钻,它是多重继承的核心问题。值得庆幸的是,我们可以用混杂物来解决这个问题。
mixin能为我们做什么?
"要 实现 一个混合器,请创建一个扩展Object的类,并且不声明构造函数。除非你想让你的mixin作为一个普通的类来使用,否则请使用
mixin关键字而不是class。"
mixin关键字是在dart 2.1中引入的,它在某些方面类似于抽象类,而在其他方面又与之不同。像 "抽象类 "一样,你可以在mixin中声明抽象的方法,并且不能被实例化。但与抽象类不同的是,你不能扩展mixin。
你可以使用关键字 "mixin"、"抽象类 "或一个普通的类作为mixin。让我们来看看如何用mixin解决上述问题。
请永远记住,mixin不是多重继承,相反,它们只是一种在多个层次中重复使用我们的类的代码的方法,而不需要扩展它们。这就像能够使用其他人的资产而不成为他们的孩子。它很酷哈! 😝
首先,我们必须创建具有perform()方法的Performer类。
class Performer {
void perform() {
print('performing...');
}
}
接下来我们创建Dancer类,其中包含一个名为perform()的方法。
mixin Dancer {
void perform() {
print('Dance...Dance...Dance..');
}
}
现在我们将声明另一个名为 "歌手 "的类,它将包含同样的方法 "perform()"。
mixin Singer {
void perform() {
print('lalaaa..laaalaaa....laaaaa');
}
}
让我们再创建一个类Musician,它将使用这两个类和Performe类。
class Musician extends Performer with Dancer,Singer {
void showTime() {
perform();
}
}
现在,如果我们尝试运行上述代码,我们会得到lalaaa...laaalaaa....laaaa的输出,你能猜到为什么吗?
当混合类时,作为 mixins 的类不是平行的,而是在使用它的类之上。这就是方法之间不冲突的原因,使我们可以使用多个类的代码,而不必处理多继承的漏洞。
如果你对此感到困惑,不要惊慌,我将解释如何评估混血儿。
对于确定在使用混血儿时哪个类的方法将被执行,请遵循以下简单的步骤。
- 如果使用mixins的类扩展了任何一个类,那么就把该类放在堆栈的顶部。 例如,
class Musician extends Performer
- 永远记住你声明mixins的顺序,这非常重要,因为它决定了哪个类更重要。如果mixins包含相同的方法,那么后面声明的mixin类将被执行(在另一个mixin之后声明会提高其 "重要性")。
在我们的例子中,我们在歌手之前声明了 "舞者",所以它更 "重要",因此会在 "表演者 "之下。例如,"class Musician extends Performer with Dancer"。
- 在
Dancer'之后,我们声明了Singer',所以把Singer'放在栈中Dancer'的下面。
- 最后,在堆栈中加入使用混血的类,即
音乐家。这个类将是最重要或最特殊的类。如果这个类包含任何与混合类或超级类相同的方法,那么这个类中的方法将被首先调用......总是如此。
明白了吗?mixins可以作为一种重用代码的方式,而不需要处理多重继承以及由此产生的问题,这就是背后的想法。
现在,我们将尝试关注一些我们可以用mixins做的其他高级事情。
😯 用mixin做一些更多的事情!
尽管我们可以使用Dart的混合器做很多普通和高级的事情,但还有一件事我们需要看一下,那就是关键字on。关键字 "on "用于限制混合器的使用,使其只能用于 "扩展 "或 "实现 "它所声明的类。为了使用 "on "关键字,你必须使用 "mixin "关键字来声明你的混合器。
下面是一个使用 "On "关键字的例子。
class A {}
class B{}
mixin X on A{}
mixin Y on B {}
class P extends A with X {} //satisfies condition as it extends A
class Q extends B with Y {} //satisfies condition as it extends B
在上面的代码中,我们限制混合器X和Y只能被分别实现或扩展A和B的类使用。
☀️结论
mixins的根基可以在Lisp中找到。社区,其最早的用途是smalltalk。Dart在很多方面都受到smalltalk的影响,它从smalltalk获得了很多灵感,包括mixin。混合器是重用你的代码的好方法,在多个类的层次结构中没有任何限制。我相信有很多事情都可以用mixin来完成。我很想看看你们都用这个创造了什么。好运! 翩翩起舞快乐
如果你有任何问题,请自由发表👇。
欢迎任何反馈😃。
如果你喜欢这个故事,你可以通过👏支持我。 你也可以在 Twitter , Facebook 或 Instagram 上关注我。
关注Flutter社区。