Flutter | Dart语法-Mixins的使用
在我开始学习Dart语法时,我见到这样一种代码:
class CurrentLocale with ChangeNotifier{
Locale _locale =Locale("zh_CN");
Locale get value => _locale;
void setLocale(locale) async{
_locale = await locale;
notifyListeners();
}
}
它与继承不同,使用了with关键字,在dart中叫Mixins(混入),这对我来说是新的概念,这篇文章便记录下对这个概念的理解:
1、什么是Mixins?
我们知道,当一些对象具有相同的行为时,我们可以将这些行为抽象出来,成为父类,让子类去继承它,达到一种复用代码的效果,但是,是不是会出现这么一种情况,比如猫和鸟都能走路,但是鸟却可以飞,这样多出的行为就没办法在父类一起实现了,还好dart为我们提供了Mixins,来解决我们在多个类层次结构中重用代码的方法。
2、怎么使用Mixins?
我们知道什么是Mixins后,接在来看看怎么使用它。
我们先创建父类Animal,假装所有动物都会走(当然不是)
class Animal{
void walk(){
print("我会走");
}
}
接着创建一个猫类一个鸟类,让他们继承动物类
class Cat extends Animal{}
class Bird extends Animal{}
这样,猫和鸟就都能调用父类的walk方法了,我们来实验下:
_testDemo(){
var cat = Cat();
cat.walk();
var bird = Bird();
bird.walk();
}
结果自然是ok。
接着鸟还能飞,于是开始定义我们可以飞的Mixins
你可以定义普通的隐式定义
class Flyer{
void fly(){
print("我会飞");
}
}
也可以定义不被实例化或扩展的抽象类
abstract class Flyer{
factory Flyer._() =>null
void fly(){
print("我会飞");
}
}
接着让你的鸟通过with关键字去混入这个Flyer
class Bird extends Animal with Flyer{}
这样我们就能用鸟的对象来调用fly方法了
_testDemo(){
var cat = Cat();
cat.walk();
var bird = Bird();
bird.walk();
bird.fly();
}
看起来似乎和其他语言中的多继承特性有些相似,但是有一个区别在于:Mixins类他是不在类层次结构中的。
或者可以这么说,Mixins并不是多继承的网状结构,而是单继承的线性结构,那么Mixins是怎么做到的呢?
我们先来看一段代码:
class A {
String getMessage() => 'A';
}
class B {
String getMessage() => 'B';
}
class P {
String getMessage() => 'P';
}
class AB extends P with A, B {
}
class BA extends P with B, A {
}
_testDemo(){
String result = '';
AB ab = AB();
result += ab.getMessage();
BA ba = BA();
result += ba.getMessage();
print(result);
}
这个result最后会输出什么呢?答案是BA
那么是怎么造成的这个结果呢?
3、线性覆盖
上面的代码很有意思,我们可以发现,似乎最后的结果和Mixins的声明顺序有关。
其实在Dart中Mixins是创建新类来实现的,比如P with A,会生成一个PA类,P和A中有重名方法,则A会覆盖掉P中的方法,同理,继续with B ,会生成PAB类,B中的同名方法又覆盖了 PA中的方法,所以最后输出了B,同理BA,其实是调用了PBA中的getMessage(),所以BA输出了A。
据此我们可以得到以下结论:
- Mixins不是类似其他语言中的多继承,而是与单继承兼容的线性特性。
- Mixins是一种抽象和重用行为状态的方法。
- 在使用Mixins时,with后面的类会覆盖前面类的同名方法。
4、什么时候使用Mixins
通过上面的内容,对Mixins应该有了一定的了解,当我们在不共享层次结构的多个类中如果想共享行为,Mixins将非常有用。在Flutter的开发中,经常会使用到Mixins,希望大家能有所收获。
最后感谢您花费宝贵的时间阅读,如果有什么想要讨论的也可以联系我,期待有缘再见!