博客 / 詳情

返回

dart中,略顯混亂繼承、接口、with等,該怎麼理解?

最近在學習flutter,研究別人的組件,剛好看到一段代碼設計,如下(精簡過後):

代碼解釋:
1、抽象類ColumnType提供了屬性defaultValue、方法test()
2、具體類ColumnTypeNumber 實現implementsColumnType
3、具體類ColumnTypeNumber 混入withColumnTypeWithNumber
4、因為2,所以需要覆蓋1中提供的成員defaultValuetest(),但是又因為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 withColumnTypeWithNumber,也implementsColumnType

疑問點:
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)。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.