<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Flutter 中不得不會的 mixin

          共 4714字,需瀏覽 10分鐘

           ·

          2021-02-04 15:11

          老孟導(dǎo)讀mixin 是 Dart 中非常重要的概念,對于未接觸過此概念的Coder來說尤其重要,最近看源碼的時候,由于對 mixin 不熟悉導(dǎo)致理解出現(xiàn)偏差,走了很多彎路,所以這篇文章介紹一下 mixin 概念。

          Dart 及 Engine 版本:

          Engine ? revision ae90085a84 Tools ? Dart 2.10.4

          請注意版本,不同的版本可能存在差異。

          先來看下官方的定義:

          Mixins are a way of reusing a class’s code in multiple class hierarchies.

          Mixins 是一種在多個類層次結(jié)構(gòu)中重用類代碼的方法。

          在來看下 Wiki 的解釋:

          In object-oriented programming languages, a mixin (or mix-in) is a class that contains methods for use by other classes without having to be the parent class of those other classes. How those other classes gain access to the mixin's methods depends on the language. Mixins are sometimes described as being "included" rather than "inherited".

          Mixins encourage code reuse and can be used to avoid the inheritance ambiguity that multiple inheritance can cause (the "diamond problem"), or to work around lack of support for multiple inheritance in a language. A mixin can also be viewed as an interface with implemented methods. This pattern is an example of enforcing the dependency inversion principle.

          翻譯如下:

          在面向?qū)ο蟮木幊陶Z言中,mixin(或mix-in)是一個類,其中包含供其他類使用的方法,而不必成為其他類的父類。這些其他類如何獲得對mixin方法的訪問權(quán)限取決于語言?;旌纤赜袝r被描述為“包含”而不是“繼承”。

          Mixins鼓勵代碼重用,并且可用于避免多重繼承可能導(dǎo)致的繼承歧義(“鉆石問題”),或解決語言中對多重繼承的支持不足的問題?;旌弦部梢钥醋魇且褜崿F(xiàn)方法的接口。此模式是強(qiáng)制執(zhí)行依賴關(guān)系反轉(zhuǎn)原理的示例。

          看完這兩段介紹,可能依然對其比較模糊,不要緊,現(xiàn)在只需對其有個概念即可,下面會詳細(xì)介紹 Mixins 的用法,我個人的理解就是:Mixins 解決了無法多重繼承的問題。

          什么時候需要使用 Mixins

          有如下場景:

          定義一個基類人(Person),它有吃(eat)的方法。

          有3個實際的人A、B、C,它們都繼承 Person,但是3個人有不同的技能:

          • A :會唱歌、跳舞
          • B:會跳舞、寫代碼
          • C:會唱歌、寫代碼

          上面的場景中唱歌、跳舞、寫代碼是一種技能,并不是每一個人都會的,所以將其定義在 Person 中是不合適的,如果各自定義為一個類,又不能同時繼承Person和唱歌、跳舞、寫代碼,如果將唱歌、跳舞、寫代碼定義為 Interface ,那么A、B、C中要各自實現(xiàn)其方法,

          那要如何實現(xiàn)呢?Mixins 出場啦。

          定義一個 Person 基類和功能類唱歌、跳舞、寫代碼:

          class?Person?{
          ??eat()?{
          ????print('Person?eat');
          ??}
          }

          class?Dance?{
          ??dance()?{
          ????print('Dance?dance');
          ??}
          }

          class?Sing?{
          ??sing()?{
          ????print('Sing?sing');
          ??}
          }

          class?Code?{
          ??code()?{
          ????print('Code?code');
          ??}
          }

          定義A、B、C:

          class?A?extends?Person?with?Dance,?Sing?{}

          class?B?extends?Person?with?Sing,?Code?{}

          class?C?extends?Person?with?Code,?Dance?{}

          注意:混合使用 with 關(guān)鍵字。

          使用:

          A?a?=?A();
          a.eat();
          a.dance();
          a.sing();

          輸出日志:

          flutter:?Person?eat
          flutter:?Dance?dance
          flutter:?Sing?sing

          可以看到 A 中有了Dance 和Sing的相關(guān)的方法。

          Dance 是一個 class,如果給其添加構(gòu)造函數(shù)會如何?

          給 Dance 添加構(gòu)造函數(shù),修改如下,

          此時發(fā)現(xiàn) A 和 C 無法編譯,出現(xiàn)如下錯誤:

          很明顯,需要 mixin 的類無法定義構(gòu)造函數(shù)。

          所以一般會將需要 mixin 的類使用 mixin 關(guān)鍵字:

          添加限定條件,使用關(guān)鍵字 on

          接著上面的場景繼續(xù),這時定義一個狗的類,目前狗這個類也可以混合 Dance 、Sing 和 Code,

          class?Dog?with?Code{}

          但是,Code 是人類獨有的技能,不希望 Dog 這個類可以mixin,所以給 Code 添加限定條件:

          使用關(guān)鍵字 on 限定Code 只能被 Person 或者其子類 mixin。

          此時 Dog 無法 mixin Code。

          添加限定后,可以重寫其方法, Code 重寫 Person 的方法:

          super 表示調(diào)用父類(Person)的方法。

          如何處理多個類有同一方法的情況

          假設(shè)有D 和 D1 兩個類,有同一個方法 d,E mixin D 和 D1:

          此時,調(diào)用 e.d 方法:

          E?e?=?E();
          e.d();

          輸出:

          flutter:?D1?d

          說明后面的將前面的覆蓋了,調(diào)換下D 和 D1的順序:

          class?E?with?D1,?D?{}

          輸出:

          flutter:?D?d

          此時在 E 中也添加 d 方法:

          輸出:

          flutter:?E?d

          說明 E 中 方法覆蓋了原來的。

          E 中 d 方法可以調(diào)用 super.d()

          輸出:

          flutter:?D?d
          flutter:?E?d

          假設(shè)現(xiàn)在有F、G、H 三個類,都有 a 方法,

          有如下定義的類:

          那么下面會輸出什么值:

          答案是:

          flutter:?G?a

          記?。夯旌项悤r,進(jìn)行混合的多個類是線性的,這是他們共有方法不沖突的原因,混合的順序非常重要,因為它決定了混合時相同的方法的處理邏輯。

          再次看下 FG 的混合情況:

          FG 繼承 H,混合 F 和 G,對于相同方法的優(yōu)先級為:G > F > H,因此共有方法 a,最后執(zhí)行的是 G 類中的 a 方法。

          那么如果 FG 中也有 a 方法會如何?

          如果本身(FG)也存在相同的方法那么優(yōu)先級:FG > G > F > H。super.a() 執(zhí)行的是 G 中的 a 方法。

          輸出結(jié)果:

          flutter:?G?a
          flutter:?FG?a

          更復(fù)雜的來啦,請看如下混合關(guān)系:

          BB 為一個抽象類,有一個構(gòu)造函數(shù),其中執(zhí)行 init 方法,GB 和 PB 為一個混合類型,限定了只有 BB 或者其子類才能混合,WFB 繼承 BB,并混合GB、PB,此時創(chuàng)建 WFB 對象,

          WFB?wfb?=?WFB();

          輸出結(jié)果是什么?

          flutter:?BB?Constructor
          flutter:?BB?init
          flutter:?GB?init
          flutter:?PB?init

          是不是很詫異,按照上面的邏輯不是應(yīng)該只調(diào)用 PB 的 init 方法嗎?

          你理解的沒有錯,的確只調(diào)用了PB 的 init 方法,但是 PB 的 init 方法中調(diào)用了super.init(),這個才是重點,PB 通過 super.init 調(diào)用到了GB中的 init 方法, GB 通過 super.init 調(diào)用到了 BB 中的 init 方法,所以最終輸出的就是上面的結(jié)果。

          這個一定要理解其中的調(diào)用順序,因為的 Flutter Framework 的入口函數(shù) runApp 中就是此形式:

          WidgetsFlutterBinding.ensureInitialized 方法如下:

          WidgetsFlutterBinding 混合結(jié)構(gòu)如下:

          class?WidgetsFlutterBinding?extends?BindingBase?with?GestureBinding,?SchedulerBinding,?ServicesBinding,?PaintingBinding,?SemanticsBinding,?RendererBinding,?WidgetsBinding?{

          BindingBase 及構(gòu)造函數(shù)如下:

          其執(zhí)行了 initInstances 和 initServiceExtensions 方法??聪旅婊旌系捻樞颍?/p>

          從后到前依次執(zhí)行其 initInstances 和 initServiceExtensions(如果有) 方法,由于 initInstances 和 initServiceExtensions 方法中首先執(zhí)行 super.initInstances()super.initServiceExtensions() ,所以最后執(zhí)行的順序為:BindingBase -> GestureBinding -> SchedulerBinding -> ServicesBinding -> PaintingBinding -> SemanticsBinding -> RendererBindinsg -> WidgetsBinding 。

          類型

          還是上面的F、G、H 三個類,那么 FG 的類型是什么,看下面的判斷會輸出什么?

          輸出:

          flutter:?FG?is?F?:?true
          flutter:?FG?is?G?:?true
          flutter:?FG?is?H?:?true

          所以混合后的類型是超類的子類型。

          總結(jié)

          1. Mixins 使我們可以在無需繼承父類的情況下為此類添加父類的“功能”,可以在同一個類中具有一個父級和多個 mixin 組件。
          2. Mixins 不可以聲明任何構(gòu)造函數(shù)。
          3. Mixins 添加限定條件使用 on 關(guān)鍵字。
          4. 混合使用 with 關(guān)鍵字,with 后面可以是 class、abstract classmixin 的類型。
          5. Mixins 不是多重繼承,相反,它只是在多個層次結(jié)構(gòu)中重用類中的代碼而無需擴(kuò)展它們的一種方式。



          你可能還喜歡


          關(guān)注「老孟Flutter」
          讓你每天進(jìn)步一點點


          瀏覽 51
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉精品视频在线 | 久久亚洲天堂 | 在线观看视频A片 | 91免费国产 | 欧美色综合一区二区三区 |