原文引用 大专栏 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 |