Dart語法Mixin機(jī)制

一、概念
“Mixins are a way of reusing a class’s code in multiple class hierarchies.” 混合是一種在多個類層次結(jié)構(gòu)中重用類代碼的方法。
從概念上我們可以理解它是為了解決代碼重用的一種方式。學(xué)習(xí)java的小伙伴可能會想到interface,Dart中的類都可以作為接口,這不是已經(jīng)有了
解決方案了嗎?為什么還需要mixin呢?

二、使用
首先我們來解決上面提到的問題,為什么要使用mixin。
我們很多語言都是采用了單繼承+接口多實現(xiàn)的方式,但是這種方式不能很好的適用于所有場景。
我們看下下面這個假設(shè)的例子:

mixin_extends2.PNG

我們通過上圖可以看出,這些學(xué)生都有一個共同的父類Student,然后又有三個抽象子類:文科班學(xué)生,理科班學(xué)生、藝術(shù)班學(xué)生。這些類具有相同的行為和能力,但是有的類又有自己獨有的行為和能力。比如文科、理科、藝術(shù)班學(xué)生都可以上數(shù)學(xué)課程,
但是只有理科班學(xué)生可以上物理課程,文科班和藝術(shù)班學(xué)生可以上地理課程,物理班學(xué)生又不可以上地理課程。那么問題就出現(xiàn)了,部分具有相同能力和行為的子類都要保留一份相同的代碼實現(xiàn),比如文科班學(xué)生類和藝術(shù)班學(xué)生類都要實現(xiàn)一份上地理課的實現(xiàn),
就產(chǎn)生了冗余。這種單繼承模型下,無法把部分子類具有相同行為能力抽象到基類中,因為對其它不具有此行為的子類來說是不合適的,例如把上地理課放在基類student中,因此只能在各自子類中實現(xiàn)。

abstract class Student{
}

abstract class GeographyClass{
  void goGeography();
}

abstract class MathClass{
  void goMath();
}

abstract class PhysicsClass{
  void goPhysics();
}

class ScienceStudent extends Student implements MathClass, GeographyClass {
  @override
  void goGeography() {
    print("上地理課");
  }

  @override
  void goMath() {
    print("上數(shù)學(xué)課");
  }
}
class LiberalStudent extends Student implements MathClass, PhysicsClass {
  @override
  void goMath() {
    print("上數(shù)學(xué)課");
  }

  @override
  void goPhysics() {
    print("上物理課");
  }
}
class ArtStudent extends Student implements MathClass, GeographyClass {
  @override
  void goGeography() {
    print("上地理課");
  }

  @override
  void goMath() {
    print("上數(shù)學(xué)課");
  }
}

從上述實現(xiàn)代碼中可以看出,子類中很多相同的冗余實現(xiàn)代碼。那么我們是不是想有一種方式可以解決這種冗余問題,是的,mixin就能很好的解決這類問題。
下面是使用mixin改寫后的代碼:

abstract class Student{}

mixin GeographyClass{
  void goGeography() {
    print("上地理課");
  }
}

mixin MathClass{
  void goMath() {
    print("上數(shù)學(xué)課");
  }
}

mixin PhysicsClass{
  void goPhysics() {
    print("上物理課");
  }
}

class ScienceStudent extends Student with MathClass, GeographyClass {
}

class LiberalStudent extends Student with MathClass, PhysicsClass {
}

class ArtStudent extends Student with MathClass, GeographyClass {
}

改寫后的代碼可以發(fā)現(xiàn),mixin很好得解決了代碼冗余問題。它能復(fù)用類中的某個功能具體實現(xiàn),而不是像接口一樣需要類去實現(xiàn)哪些能力。因此mixin多繼承模型很好解決了單繼承模型帶來的冗余問題。
注意:對mixin關(guān)鍵字的支持是在Dart 2.1 版本引入的,早期的版本使用abstract class來代替的。
其實在java8和Kotlin中為了解決代碼重復(fù)冗余問題,使用了接口的default實現(xiàn)來解決這個問題:

interface ITest {
    default void test(){}
   }

三、線性化
mixin是線性化的,這句話如何理解呢?首先我們看下下面的例子:

mixin TA {
  void t() {
    print("TA");
  }
}

mixin TB {
  void t() {
    print("TB");
  }
}

class TC {
  void t() {
    print("TC");
  }
}

class Mix1 with TA, TB {//TB
}
class Mix2 with TB, TA {//TA
}

我們會得到如下結(jié)果:

TB
TA

此時你可能會總結(jié)得到規(guī)律,with后面多個類中有相同的方法,會調(diào)用距離with關(guān)鍵字最遠(yuǎn)的類中的方法。下面我們得到結(jié)論:
mixin混入類中時,Dart中的Mixins通過創(chuàng)建一個新類來實現(xiàn),該類將mixin的實現(xiàn)層疊在一個超類之上以創(chuàng)建一個新類 ,它不是“在超類中”,而是在超類的“頂部。
聲明 mixin 的順序代表了繼承鏈的繼承順序,聲明在后面的 mixin,一般會最先執(zhí)行。
接下來我們再看下面的例子:

class T {
  void fun() {
    print("A");
  }
}

mixin TA on T{
  void fun() {
    super.fun();
    cover();
    print("TA");
  }

  void cover() {
    print("cover TA");
  }
}

mixin TB on T {
  void fun() {
    super.fun();
    print("TB");
  }

  void cover() {
    print("cover TB");
  }
}

class A extends T with TA, TB {} // TB

class B extends T with TB, TA {} // TA

void main() {
  A a = A();
  a.fun();
}

按照我們剛才的理解,我們會得到如下結(jié)果:

   A
  cover TA
  TA
  TB

實際上,我們輸出的結(jié)果是:

    A
    cover TB
    TA
    TB

回想我們得到的結(jié)論,在mixin繼承鏈中,最后聲明的mixin會把前面聲明的相同方法覆蓋掉。這時,即使我們代碼中調(diào)用了TA的cover方法,實際上也會被TB類中的cover方法覆蓋掉。因此最終調(diào)用的還是MB中的方法。

四、總結(jié)
我們大致總結(jié)了mixin的機(jī)制和使用,mixin 是一個強(qiáng)大的概念,我們可以跨越類的層次結(jié)構(gòu)重用代碼。在我們看Flutter源碼時,經(jīng)常會看到使用這個功能,我也是在看Flutter代碼時,看到這個關(guān)鍵字然后進(jìn)行補(bǔ)腦的。
1.Mixins并不是經(jīng)典意義上獲得多重繼承的方法。
2.Mixins是一種抽象和復(fù)用一系列操作和狀態(tài)的方式,而且生成多個中間的mixin類。
3.它是線性的,因此與單繼承兼容。
4.Mixins除了繼承Object外,不可以繼承任何其他類; Mixins不可以定義構(gòu)造方法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容