[Dart翻译]Dart for Flutter : Dart中的Mixin

156 阅读8分钟

本文由 简悦SimpRead 转码,原文地址 medium.com

在面向对象的编程语言中,Mixin是一个包含方法的类,供其他c......。

1.gif

把Class混合到一起

我是一个拥有大量Java和一般编程经验的Android开发者。今年Flutter从其测试版发布开始就获得了大量的曝光,吸引了许多来自Android、IOS甚至是网络的开发者。

在Flutter 1.0发布后,它几乎勾起了所有移动开发者的好奇心。当我第一次看到它时,它似乎非常有趣,所以我决定给它一个机会。

当我意识到我必须学习一种新的编程语言才能开始使用Flutter时,我几乎打算跳过尝试它。学习一门新的编程语言总是一个耗时的过程。也就是说,当我看了Dart网站上的一些例子后,一切都改变了。Dart给人的感觉就像家一样。它是一种非常简洁易懂的语言,特别是如果你有Java、JavaScript、C#或任何其他_面向对象的编程语言的编程背景。你将在几个小时内启动并运行Dart程序。

从我使用Dart的时间来看,我觉得有一个话题有点棘手,那就是混合器。对于Java开发者来说,这是一个完全陌生的概念,因为Java不支持多重继承或混合体。Java试图通过使用接口来弥补这一缺陷,但这并不像 mixins 那样有用或灵活。

所以,让我们先试着了解一下什么是 mixins

💫 mixin到底是什么?

1.gif

我认为混合体的最简明定义是由维基百科提供的。

"在面向对象的编程语言中,一个 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();  
   }
}

image.png

感到困惑?这就是编译器在我们试图运行这段代码时的感觉。因为我们没有实际的方法来决定哪个是正确的方法要调用。这种情况被称为致命的死亡之钻,它是多重继承的核心问题。值得庆幸的是,我们可以用混杂物来解决这个问题。

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

image.png

  • 永远记住你声明mixins的顺序,这非常重要,因为它决定了哪个类更重要。如果mixins包含相同的方法,那么后面声明的mixin类将被执行(在另一个mixin之后声明会提高其 "重要性")。

在我们的例子中,我们在歌手之前声明了 "舞者",所以它更 "重要",因此会在 "表演者 "之下。例如,"class Musician extends Performer with Dancer"。

image.png

  • Dancer'之后,我们声明了Singer',所以把Singer'放在栈中Dancer'的下面。

image.png

  • 最后,在堆栈中加入使用混血的类,即音乐家。这个类将是最重要或最特殊的类。如果这个类包含任何与混合类或超级类相同的方法,那么这个类中的方法将被首先调用......总是如此。

image.png

明白了吗?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

在上面的代码中,我们限制混合器XY只能被分别实现或扩展AB的类使用。

☀️结论

mixins的根基可以在Lisp中找到。社区,其最早的用途是smalltalk。Dart在很多方面都受到smalltalk的影响,它从smalltalk获得了很多灵感,包括mixin。混合器是重用你的代码的好方法,在多个类的层次结构中没有任何限制。我相信有很多事情都可以用mixin来完成。我很想看看你们都用这个创造了什么。好运! 翩翩起舞快乐

如果你有任何问题,请自由发表👇。

欢迎任何反馈😃。

如果你喜欢这个故事,你可以通过👏支持我。 你也可以在 Twitter , FacebookInstagram 上关注我。

关注Flutter社区。

twitter.com/FlutterComm


www.deepl.com 翻译