浅谈Dart中的Mixin

冷暖自知 提交于 2019-11-28 14:53:53

原文引用 大专栏  https://www.dazhuanlan.com/2019/08/26/5d6335095dd24/


这篇本来要跟上一篇一起写

直到我发现Dart中Mixin的观念其实多到可以自成一篇QQ

观念

先来讲讲一些观念:

看完上述这几点,是不是心里只有 “马的,工三小?”

举个例子

接下来的话就来举个例子好了

现在有两种技能: Teach and Drive

而且有两种职业: Teacher and Driver

现在假设这两个职业都各持有Teach and Drive这两个技能

Java v.s. Dart

Java版本:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
abstract class  {    }interface Teach {    void canTeach();}interface Drive {    void canDrive();}class Teacher extends Human implements Teach, Drive {        public void canTeach() {        System.out.println("Yes, a human can teach.");    }    @Override    public void canDrive() {        System.out.println("Yes, a human can drive.");    }}class Driver extends Human implements Teach, Drive {    @Override    public void canTeach() {        System.out.println("Yes, a human can teach.");    }    @Override    public void canDrive() {        System.out.println("Yes, a human can drive.");    }}public static void main(String[] args) {         Teacher teacher = new Teacher();    teacher.canTeach();    teacher.canDrive();      Driver driver = new Driver();    driver.canTeach();    driver.canDrive();}

Dart版本:

12345678910111213141516171819202122232425262728293031
abstract class Human {   }class Teach {  void canTeach() {    print("Yes, a human can teach.");  }}class Drive {  void canDrive() {    print("Yes, a human can drive.");  }}class Teacher extends Human with Teach, Drive {}class Driver extends Human with Teach, Drive {}void main() {    Teacher teacher = new Teacher();  teacher.canTeach();  teacher.canDrive();    Driver driver = new Driver();  driver.canTeach();  driver.canDrive();  }

输出均为:

1234
Yes, a human can teach.Yes, a human can drive.Yes, a human can teach.Yes, a human can drive.

这里可以看到在Java版本的两个职业中,实践方法(技能)时出现重复的程序

而这里Dart版本中的Mixin类自带方法实现,从而解决了这个问题

(不过Java 8以上的default method也有同样的效果)

使Mixin类无法实例化

这里可以使用关键字mixin

123456
mixin Teach {  // 这里就是一个标准的Mixin类,无法实例化  void canTeach() {    print("Yes, a human can teach.");  }}

或者是改为abstract class

然后给定该类一个private constructor(dash代表私有),并设回传值为null

12345678
abstract class Drive {  // 这样一来Drive既不能扩充也不能实例化了  factory Drive._() => null;    void canDrive() {    print("Yes, a human can drive.");  }}

mixin on

现在我们修改一下设定

假设说只有会教书的人能使用Teach这个技能呢?

这时我们可以用到mixin on这个关键字

123456789101112131415161718192021222324252627282930313233343536373839404142434445
abstract class Human {  // Some properties and methods...}class WhoCanTeach extends Human {    // 会教书的人}mixin Teach on WhoCanTeach {  // 这里就指定了只有extends WhoCanTeach或implements WhoCanTeach的类才能with Teach  void canTeach() {    print("Yes, a teacher can teach.");  }}abstract class Drive {  factory Drive._() => null;    void canDrive() {    print("Yes, a human can drive.");  }}class Teacher extends WhoCanTeach with Teach, Drive {  // Correct.}class Driver extends Human with Teach, Drive {  // Error: Driver does not implement WhoCanTeach.}class Driver extends Human with Drive {  // Correct.}void main() {    Teacher teacher = new Teacher();  teacher.canTeach();  teacher.canDrive();    Driver driver = new Driver();  driver.canDrive();  }

输出:

123
Yes, a teacher can teach.Yes, a human can drive.Yes, a human can drive.

线性化

看一下这个例子

1234567891011121314151617181920
class Human {  String getStatus() => "Full of energy!";}class Student {  String getStatus() => "I'm tired!";}class Engineer {  String getStatus() => "I'm dying...";}class Me extends Human with Student, Engineer {}void main() {    Me me = new Me();  print(me.getStatus());  }

好的,这里究竟会印出什么东西来呢?

答案是 “I’m dying…” QAQ

先讲结论: 越后面的Mixin类优先级别越高,等于是倒过来看啦~

拆解

上面的东西相当于这样

123456789101112131415161718192021222324
class Human {  String getStatus() => "Full of energy!";}class Student {  String getStatus() => "I'm tired!";}class Engineer {  String getStatus() => "I'm dying...";}class HumanWhoIsStudent extends Human with Student {}class HumanWhoIsStudentAndEngineer extends HumanWhoIsStudent with Engineer {}class Me extends HumanWhoIsStudentAndEngineer {}void main() {    Me me = new Me();  print(me.getStatus());  }

简单来说,Mixin像是在实现一条线性的继承链

实例化后的类型

一样是上面的例子

123456789
void main() {    Me me = new Me();  print(me is Me);  print(me is Engineer);  print(me is Student);  print(me is Human);  }

输出:

1234
truetruetruetrue
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!