最近在學習flutter,研究別人的組件,剛好看到一段代碼設計,如下(精簡過後):
代碼解釋:
1、抽象類ColumnType提供了屬性defaultValue、方法test();
2、具體類ColumnTypeNumber 實現implements了ColumnType;
3、具體類ColumnTypeNumber 混入with了ColumnTypeWithNumber;
4、因為2,所以需要覆蓋1中提供的成員defaultValue、test(),但是又因為3(定義了方法test()),所以該類不需要覆蓋test(),但是又不需要寫override,但是 mixin ColumnTypeWithNumber 裏面又不能覆蓋抽象類的屬性defaultValue;
5、反而mixin ColumnTypeWithNumber定義的屬性format,卻成了具體類ColumnTypeNumber需要覆蓋的成員;
abstract interface class ColumnType {
/// 定義一個屬性
dynamic get defaultValue;
/// 定義一個抽象方法
void test();
}
class ColumnTypeNumber with ColumnTypeWithNumber implements ColumnType {
@override
final dynamic defaultValue;
@override
final String format;
/// 構造函數
const ColumnTypeNumber({this.defaultValue, this.format = ''});
}
mixin ColumnTypeWithNumber {
String get format;
void test() {}
}
如果沒有ColumnTypeWithNumber,那麼ColumnTypeNumber實現抽象類後,代碼如下:
abstract interface class ColumnType {
/// 定義一個屬性
dynamic get defaultValue;
/// 定義一個抽象方法
void test();
}
class ColumnTypeNumber implements ColumnType {
@override
final dynamic defaultValue;
@override
void test() {}
/// 構造函數
const ColumnTypeNumber({this.defaultValue});
}
直接 override 屬性 defaultValue 方法 test() 即可;但是加入with 後(成了上面第一段代碼),疑問就來了,mixin可以理解是一種提供共享代碼的方式。
具體類ColumnTypeNumber with了ColumnTypeWithNumber,也implements了ColumnType
疑問點:
1、因為ColumnTypeNumber with ColumnTypeWithNumber,所以表示擁有了test(),但是卻可以不用@override標記;
2、因為ColumnTypeNumber with ColumnTypeWithNumber,但是卻不得不@override裏面的屬性format,這看上去又像是“實現了”接口一般(所以需要override裏面的成員)。
3、mixin ColumnTypeWithNumber裏面的方法能夠當值覆蓋抽象類的方法,但是裏面卻不能夠覆蓋抽象類的屬性defaultValue;
4、源碼比這個複雜,會實現多個接口,with多個mixin代碼塊,所以導致具體類裏面的屬性、方法搞不清來自哪裏?
5、源碼裏面很多奇怪的寫法,例如上面提到的abstract interface class三個關鍵詞修飾。感覺“靈活”但是“凌亂”。
該怎麼來記憶(理解)這一塊擰巴的邏輯呢?
結論:想來想去,最簡單的辦法是把with可以理解為“繼承”,如果定義了抽象成員,如String get format;(沒有實現),那麼就需要override,如果是具體實現的成員,如test(),那就可以理解為被繼承的成員,如果方法名和其他抽象接口同名,剛好可以當作覆蓋作用(可以不寫override)。