mixins
做爲Flutter的重要特性,值得好好研究一下bash
mixins
的中文意思是混入,就是在類中混入其餘功能。ide
Dart中的定義是:函數
Mixins are a way of reusing a class’s code in multiple class hierarchies.
複製代碼
Mixins是一種在多個類層次結構中複用類代碼的方法。post
能夠看出Mixins最重要的功能是複用代碼,咱們先看下JAVA,複用代碼的方式有哪些:ui
繼承spa
子類能夠複用父類的方法和屬性,可是JAVA裏的繼承只能單繼承。code
組合對象
將要複用的代碼,封裝成類A,讓其餘類持有A的實例,看上去貌似解決了複用代碼的問題,可是一方面,每一個類持有的A的實例是不一樣的,有多少個類,就總共有多少個A的實例,並且另外一方面,即便A使用單例,使用起來也很不方便。繼承
接口接口
定義一個接口interface,類實現interface,這樣雖然接口是同一個,可是實現倒是分散的,能複用的代碼是有限的。
因此在JAVA裏想要複用代碼,限制是不少的。
這就有了mixins
的概念,mixins
最先的根源來自於Lisp,由於Dart也受到smalltakk的影響,因此Dart引入了mixins
的概念,
在維基百科中有對mixins
最準確的定義:
在面向對象的語言中,mixins類是一個能夠把本身的方法提供給其餘類使用,但卻不須要成爲其餘類的父類。
複製代碼
mixins
是要經過非繼承的方式來複用類中的代碼。
這裏舉個例子,有一個類A,A中有一個方法a(),還有一個方法B,也想使用a()方法,並且不能用繼承,那麼這時候就須要用到mixins,類A就是mixins類(混入類),類B就是要被mixins的類,對應的Dart代碼以下:
類A mixins 到 B
class A {
String content = 'A Class';
void a(){
print("a");
}
}
class B with A{
}
B b = new B();
print(b.content);
b.a();
複製代碼
輸出是:
A Class
a
複製代碼
將類A mixins 到 B,B可使用A的屬性和方法,B就具有了A的功能,可是須要強調的是:
mixins要用到的關鍵字 with
怎麼來理解with
呢?很簡單:
繼承 -> extends
mixins -> with
繼承和mixins是同樣的,是語言的特性,with和extends是關鍵字。
由於mixins使用的條件,隨着Dart版本一直在變,這裏講的是Dart2.1中使用mixins的條件:
看下面代碼:
class A {
void a(){
print("a");
}
}
class A1 {
void a1(){
print("a1");
}
}
class B with A,A1{
}
B b = new B();
b.a();
b.a1();
複製代碼
輸出是:
a
a1
複製代碼
可是,若是A和A1的方法相同,並且調換A和A1的順序,在被mixins的類中實現同一個方法呢,看下面的代碼:
class A {
void a(){
print("a");
}
}
class A1 {
void a(){
print("a1");
}
}
class B with A,A1{
}
class B1 with A1,A{
}
class B2 with A,A1{
void a(){
print("b2");
}
}
class C {
void a(){
print("a1");
}
}
class B3 extends C with A,A1{
}
class B4 extends C with A1,A{
}
class B5 extends C with A,A1{
void a(){
print("b5");
}
}
B b = new B();
B1 b1 = new B1();
B2 b2 = new B2();
B3 b3 = new B3();
B4 b4 = new B4();
B5 b5 = new B5();
b.a();
b1.a();
b2.a();
b3.a();
b4.a();
b5.a();
複製代碼
會是什麼樣的結果呢?
Mixins in Dart work by creating a new class that layers the implementation of the mixin
on top of a superclass to create a new class — it is not 「on the side」 but 「on top」 of
the superclass, so there is no ambiguity in how to resolve lookups.
複製代碼
以
class B3 extends C with A,A1{
}
複製代碼
爲例,能夠分解爲:
class CA = C with A;
class CAA1 = CA with A1;
class B3 extends CAA1{
}
複製代碼
mixins不是多繼承
Mixins is not a way to get multiple inheritance in the classical sense. Mixins is a way to abstract and reuse a family of operations and state. It is similar to the reuse you get from extending a class, but it is compatible with single-inheritance because it is linear.
複製代碼
因此輸出結果是:
a1
a
b2
a1
a
b5
複製代碼
mixins的實例類型是什麼?
很簡單,mixins的類型就是其超類的子類型,因此:
B3 b3 = B3();
print(b3 is C);
print(b3 is A);
print(b3 is A1);
複製代碼
都會爲true
on
關鍵字,以前是用於try catch,用於指定異常的類型的。
此次,on
只能用於被mixins
標記的類,例如mixins X on A
,意思是要mixins X的話,得先接口實現或者繼承A。這裏A能夠是類,也能夠是接口,可是在mixins的時候用法有區別.
想看接口的請看個人這篇文章Flutter Dart語法(1):extends 、 implements 、 with的用法與區別
用繼承:
lass A {
void a(){
print("a");
}
}
mixin X on A{
void x(){
print("x");
}
}
class mixinsX extends A with X{
}
複製代碼
得首先實現這個接口,而後再用mix
class A {
void a(){
print("a");
}
}
mixin X on A{
void x(){
print("x");
}
}
class implA implements A{
@override
void a() {
// TODO: implement a
}
}
class mixinsX2 extends implA with X{
}
複製代碼