Flutter - 繼承(extends)/混合 mixins (with)/接口實現(xiàn)(implements)

類型 解決什么問題 使用場景 限制
extends 子類繼承 子類繼承父類 可以有構(gòu)造方法和實例變量
Mixin(with) 實現(xiàn)類似多繼承糠赦,能力集 不通過繼承会傲,獲取一個類的能力 不能有構(gòu)造方法,可以有實例變量
Extension(on) 給系統(tǒng)類【例如String類添加功能】 在無法修改被擴展類源碼的情況下 不能有構(gòu)造方法和實例變量
Implement 聲明和實現(xiàn)的解耦 模版方法的實現(xiàn)【設(shè)計模式的一種】 暫無

繼承(extends)

使用extends關(guān)鍵詞來繼承父類

  • 子類會繼承父類里面可見的屬性和方法 但是不會繼承構(gòu)造函數(shù)
  • 子類能復(fù)寫父類的方法 getter和setter
  • 子類重寫超類的方法拙泽,要用@override
  • 子類調(diào)用超類的方法唆铐,要用super
  • 子類可以繼承父類的非私有變量 (類中私有變量和函數(shù)的定義:名稱前面帶_)
class Person {
  String? name;
  int? age;

  /// 構(gòu)造函數(shù)
  Person(this.name);

  /// 私有屬性,對于子類不可見
  String? _birthDay;

  /// 計算屬性
  bool get isAdult => (age ?? 0) >= 18;

  void run() {
    print('Person runing');
  }
}

class Student extends Person {
  /// 子類構(gòu)造函數(shù)
  Student(String? name) : super(name);

  /// 重寫父類屬性
  @override
  bool get isAdult => (age ?? 0) > 20;

  @override
  void run() {
    // super.run();
    print('Student runing');
  }

  /// 子類自有方法
  void study() {
    print("Student can studying");
  }
}

void main() {
  Student student = Student("li sha");

  /// 調(diào)用自己方法
  student.study(); // Student can studying
  /// 訪問父類屬性
  student.age = 18;

  /// 調(diào)用父類方法
  student.run(); // Person runing

  print(student.isAdult); // false

  /// 繼承中 多態(tài)的使用
  Person person = Student('jekson ');
  person.run(); //Student runing

  // Tips: Error 這里無法訪問到子類方法奔滑,因為使用多態(tài)生成的對象是Person,Person中沒有study方法
  // person.study(); //Student runing

  /// 使用is 意思是:將person 轉(zhuǎn)化成 Student對像,就可以訪問子類方法了
  if (person is Student) {
    person.study();
  }
}

tips: 注意繼承中 多態(tài)的使用

混合 mixins (with)

mixins的中文意思是混入(兩個類混合在一起)顺少,就是在類中混入其他功能朋其。簡單的理解,就是在現(xiàn)有類的基礎(chǔ)上脆炎,引入一些新的變量和方法梅猿。

  • 作為mixins的類只能繼承自O(shè)bject,不能繼承其他類
  • 作為mixins的類不能有構(gòu)造函數(shù)
  • 一個類可以mixins多個mixins類
  • mixins不是繼承秒裕,也不是接口袱蚓,而是一種全新的特性。
最簡單的mixin

mixin本身可以是抽象的几蜻,可以定義各種方法屬性喇潘,也可以是抽象的,等后續(xù)類去實現(xiàn)

void main(List<String> args) {
  XuModel model = XuModel();
  model.xuTest2();
  model.xutest1();
  print('xuValue: ${model.xuValue}');
}

/// mixin本身可以是抽象的梭稚,可以定義各種方法屬性颖低,也可以是抽象的,等后續(xù)類去實現(xiàn)
mixin TestXuMixin {
  // 定義屬性
  var xuValue = 3;
  // 抽象方法
  void xutest1();

  void xuTest2() {
    print('xuTest2');
  }
}


class XuModel with TestXuMixin {
  @override
  void xutest1() {
    // 該函數(shù)mixin 定義未實現(xiàn)弧烤,混入對象忱屑,必須要實現(xiàn)
    print("xutest1 - xuValue : $xuValue");
  }
}
基于某個類型的mixin

當(dāng)使用on關(guān)鍵字(限定類型),則表示該mixin只能在那個類的子類使用了暇昂,那么結(jié)果顯然的莺戒,mixin中可以調(diào)用那個類定義的方法、屬性

class BaseObject {
  void method() {
    print('call method');
  }
}

mixin TestMixin on BaseObject {
  void test() {
    print('test');
  }

  int testInt = 1;
  void test2() {
    method();
  }

  void test3(); // 抽象方法
}

class Test extends BaseObject with TestMixin {
  @override
  void test3() {
    // TODO: implement test3
  }
}

void main() {
  Test().test(); // test
  print(Test().testInt); // 1
  Test().test2(); // call method
}
多個mixin

如果mixin存在沖突的部分急波,后面會覆蓋前面的从铲,沒有沖突的則會保留,所以可以存在后面的mixin修改了前面的mixin的一部分邏輯的情況澄暮,不需要直接繼承即可實現(xiàn)覆蓋食店,避免了更復(fù)雜的繼承關(guān)系

mixin TestMixin {
  void test() {
    print('test');
  }

  int testInt = 1;

  void test2();
}

mixin TestMixin2 {
  int testInt = 2;

  void test3() {
    print('test3');
  }
}

class Test with TestMixin, TestMixin2 {
  @override
  test2() {
    print('test2');
  }
}

void main() {
  Test().test(); // test
  print(Test().testInt); // 2 后面會覆蓋前面的mixin
  Test().test2(); // test2
  Test().test3(); // test3
}

mixin實現(xiàn)多重繼承
mixin TestMixin on BaseClass {
  void init() {
    print('TestMixin init start');
    super.init();
    print('TestMixin init end');
  }
}

mixin TestMixin2 on BaseClass {
  void init() {
    print('TestMixin2 init start');
    super.init();
    print('TestMixin2 init end');
  }
}

class BaseClass {
  void init() {
    print('Base init');
  }

  BaseClass() {
    init();
  }
}

class TestClass extends BaseClass with TestMixin, TestMixin2 {
  @override
  void init() {
    print('TestClass init start');
    super.init();
    print('TestClass init end');
  }
}

void main() {
  TestClass();

  /// TestClass init start
  /// TestMixin2 init start
  /// TestMixin init start
  /// Base init
  /// TestMixin init end
  /// TestMixin2 init end
  /// TestClass init end
}

接口實現(xiàn)(implements)

接口的實現(xiàn)渣淤,基于定義的一個抽象類,抽象類中僅定義方法吉嫩,沒有具體的實現(xiàn)价认,子類通過implements的方法,在子類中實現(xiàn)具體的方法自娩。

  • implements與extends最?的不同就是允許后?接上多個普通或者抽象類用踩,當(dāng)我們使?B implement A修飾時,那么A中的所有的屬性和?法都要在B中實現(xiàn)忙迁,?論它原來是抽象?法還是普通?法脐彩。
abstract class Run {
  var runValue;
  void runing() {
    print('runding');
  }
}

abstract class Eat {
  void eat();
}

class Person implements Run, Eat {
  @override
  void runing() {
    print("Person runing");
  }

  @override
  void eat() {
    print("Person eating");
  }

  @override
  var runValue = 100;
}

class Lion extends Run with Eat {
  /// 抽象類中實現(xiàn)的方法
  /// 繼承抽象類可以不用實現(xiàn)(子類繼承父類方法,可以選擇是否重寫)
  @override
  void runing() {
    /// 繼承抽象類可以調(diào)用super
    super.runing();
    print("Lion runing");
  }

  @override
  void eat() {
    print("Lion eating");
  }
}

void main(List<String> args) {
  Person().runing();
  Person().eat();

  Lion().eat();
  Lion().runing();
}

tips:

mixin:定義了組塊姊扔。

mixin on:限定了使?組塊的宿主必須要繼承于某個特定的類惠奸;在mixin中可以訪問到該特定類的成員和?法。

with負(fù)責(zé)組合組塊恰梢,而with后?跟的類并不?定需要是mixin的佛南,abstract class 和普通類都可以。

extends with 修飾會覆蓋同名方法嵌言,with中后一個覆蓋前一個

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嗅回,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子摧茴,更是在濱河造成了極大的恐慌绵载,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件苛白,死亡現(xiàn)場離奇詭異娃豹,居然都是意外死亡,警方通過查閱死者的電腦和手機购裙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門培愁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人缓窜,你說我怎么就攤上這事定续。” “怎么了禾锤?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵私股,是天一觀的道長。 經(jīng)常有香客問我恩掷,道長倡鲸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任黄娘,我火速辦了婚禮峭状,結(jié)果婚禮上克滴,老公的妹妹穿的比我還像新娘。我一直安慰自己优床,他們只是感情好劝赔,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著胆敞,像睡著了一般着帽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上移层,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天仍翰,我揣著相機與錄音,去河邊找鬼观话。 笑死予借,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的频蛔。 我是一名探鬼主播灵迫,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼帽驯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起书闸,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤尼变,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后浆劲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嫌术,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年牌借,在試婚紗的時候發(fā)現(xiàn)自己被綠了度气。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡膨报,死狀恐怖磷籍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情现柠,我是刑警寧澤院领,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站够吩,受9級特大地震影響比然,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜周循,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一强法、第九天 我趴在偏房一處隱蔽的房頂上張望万俗。 院中可真熱鬧,春花似錦饮怯、人聲如沸闰歪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽课竣。三九已至,卻和暖如春置媳,著一層夾襖步出監(jiān)牢的瞬間于樟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工拇囊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留迂曲,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓寥袭,卻偏偏與公主長得像路捧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子传黄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容