前言
? 在學習Flutter原始碼的時候,看到各種復雜的mixin和on,為了便于后續Flutter的學習,這里有必要一起來份詳細Dart 的 Mixin機制,
什么是mixins
首先看看官方檔案的定義:
Mixins are a way of reusing a class’s code in multiple class hierarchies.
即:Mixins是用來復用多個類之間的代碼,減少耦合,
再來看看維基百科對它的定義:
mixin是面向物件程式設計語言中的類,提供了方法的實作,其他類可以訪問mixin類的方法、變數而不必成為其子類,
這兩種解釋我任務維基百科描述的更通俗一點,下面我們來詳細解釋:
講解
假如我們有兩個類A,B,現在需要使用mixins定義類T
class T = A with B;
//或
class T extends A with B {}
那么我們得到結果class T是什么樣的? 假設我們A類中的所有方法為AM,B類中所有的方法集合叫BM,那么T中的方法集合就為:
BM U (AM-BM)
即:T中的方法為A 和 B類中方法的集合,如果有重復方法,取B中的方法(with 最右側的方法)
上面偽代碼就是最直接簡單的方式,相信大家應該都能看懂,下面我們來舉個例子詳細介紹一下
我們來舉幾個例子
1. A with B
//A
class A {
a() {
print('A.a()');
}
b() {
print('A.b()');
}
}
//B
class B {
a() {
print('B.a()');
}
}
//Z
class Z extends A with B {}
void main() {
Z z = Z();
z.a();
}
根據上面偽代碼AM U (AM-BM)講解(Z的方法為A,B方法集合,有重復方法取with最右邊類的方法),得出Z類中最終包含的方法應該是:B.a(),A.b()
代碼輸出結果是:
B.a()
2. A with B,C
A with B, C可以理解為:(A with B) with C
//A
class A {
a() {
print('A.a()');
}
b() {
print('A.b()');
}
}
//B
class B {
a() {
print('B.a()');
}
b() {
print('B.b()');
}
c() {
print('B.c()');
}
}
//C
class C {
a() {
print('C.a()');
}
}
//Z
class Z extends A with B, C {}
void main() {
Z z = new Z();
z.a();
z.b();
z.c();
}
根據上面的邏輯整理最終方法集合公式為CM U (BM - CM) U (AM - BM - CM),最終Z包含的方法應該是:C.a(), B.b(), B.c()
代碼輸出結果是:
C.a()
B.b()
B.c()
下面是重點關注容易被忽略的關于mixin機制里面super的注意事項
abstract class BaseA {
BaseA() {
initInstances();
}
initInstances() {
//do nothing
}
}
mixin B on BaseA {
@override
initInstances() {
super.initInstances();
print('B');
}
}
mixin C on BaseA {
@override
initInstances() {
super.initInstances();
print('C');
}
}
mixin D on BaseA {
@override
initInstances() {
super.initInstances();
print('D');
}
}
class T extends BaseA with B, C, D {
static void init() {
T();
}
}
void main() {
T.init();
}
相信上面的代碼如果洗掉B,C,D各個類里面的super.initInstances()方法呼叫就很容易得出結論知道輸出結果是:D,
但是這里加上super.initInstances()呼叫結果卻截然不同,我們只需要理解在mixin機制中,每呼叫一個方法都會類似從最右邊開始查找需要呼叫的方法,一直查找到最左邊的基類,一旦找到就停止查找然后呼叫到該方法,super也是類似,通過super.method呼叫的方法,會從當前類往左去查找metod方法;所以上面代碼的輸出結果就是:B,C,D
思考:上面如果我們將B,C,D類中的super.initInstances()和print(’*’)順序顛倒過來會輸出什么
總結
? 關于Mixins還有很多需要注意的細節,這里我們需要通過demo多多練習,有時候通過Mixin機制我們可以跨越多個類的層次實作代碼的重用,特別是Mixins機制中super的使用,在Flutter原始碼中也經常使用,需要多多練習才能理解透徹,
? 本文主要是自己通過Demo的 一些理解,如果有不同的見解,歡迎評論交流,
思考
下面模擬Flutter runApp中WidgetsFlutterBinding初始化的方式,思考下輸出的是什么:
abstract class BindingBase {
BindingBase() {
print('constructor A');
initInstances();
}
initInstances() {
//do nothing
}
}
mixin ABinding on BindingBase {
@override
initInstances() {
super.initInstances();
print('ABinding.initInstances()');
}
}
mixin BBinding on BindingBase {
@override
initInstances() {
super.initInstances();
print('BBinding.initInstances()');
}
}
mixin CBinding on BindingBase {
@override
initInstances() {
super.initInstances();
print('CBinding.initInstances()');
}
}
class WidgetsFlutterBinding extends BindingBase
with ABinding, BBinding, CBinding {
static void ensureInitialized() {
WidgetsFlutterBinding();
}
}
void main() {
WidgetsFlutterBinding.ensureInitialized();
}
歡迎評論區給出答案討論
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/312158.html
標籤:其他
