[譯]Flutter - Dart的Mixin

原文在這裏。寫的不錯,推薦各位看原文。編程

這裏補充一下Mixin的定義: 只要一個類是繼承自Object的並且沒有定義構造方法,那麼這個類能夠是一個Mixin了。固然,若是你想讓mixin的定義更加的清晰,可使用mixin關鍵字開頭來定義。具體請參考這裏app

原文截圖體會一下風格。編程語言

正文

在經典的面向對象編程語言裏必定會有常規的類抽象類接口。固然,Dart也有它本身的接口,不過那是另外的文章要說的。有的時候陰影裏潛伏者另外的野獸:Mixin!這是作什麼的,如何使用?咱們來一塊兒發現。ide

沒有mixin的世界

假設你在構建一個模擬野生動物的app,那麼你須要一個Mosquito(蚊子)類。做爲一個有預見性的開發人員,你會抽象蚊子們有的共通的東西而後放在一個抽象類裏。ui

abstract class Insect {
  void crawl() {
    print('crawling');
  }
}

abstract class AirborneInsect extends Insect {
  void flutter() {
    print('fluttering');
  }

  void buzz() {
    print('buzzing annoyingly')
  }
}

class Mosquito extends AirborneInsect {
  void doMosquitoThing() {
    crawl();
    flutter();
    buzz();
    print('sucking blood');
  }
}
複製代碼

很棒!你已經作到了!添加新的昆蟲就如同微風拂過同樣,根本不會有代碼的冗餘出現。。。一直到你發現你須要一個Swallow類(就是一種能夠吃掉整個蚊子的東西)。spa

一樣的也有不少鳥類共有的東西,咱們能夠建立一個Bird類。這個時候問題就出現了 -- 鳥也會振動翅膀!可是,你無法把flutter方法從AirboneInsect類裏面提取出來組成一個新的類Flutteringcode

爲何?Bird類能夠繼承Fluttering類,可是AirboneInsect不能夠,它已經繼承了Insect類了。Dart可不支持多繼承(真很好)。cdn

這下,你須要給Bird類添加一個flutter方法了。代碼冗餘發生了!對象

abstract class Bird {
  void chirp() {
    print('chirp chirp');
  }

  // Duplicate method
  void flutter() {
    print('fluttering');
  }
}

class Swallow extends Bird {
  void doSwallowThing() {
    chirp();
    flutter();
    print('eating a mosquito');
  }
}
複製代碼

使用mixin

Mixin的定義是「一種把類代碼用在多個繼承樹的方法」。簡單的說,mixin讓你不用繼承就能夠引入代碼塊的方法。聲明一個mixin很是的簡單:blog

mixin Fluttering {
    void flutter() {
        pring('fluttering');
    }
}
複製代碼

這個mixin能夠用在常規的類上面也能夠用在抽象類,只須要一個with關鍵字。在野生動物模擬app例子裏,你也許要用在抽象類上了。

mixin Fluttering {
  void flutter() {
    print('fluttering');
  }
}

abstract class Insect {
  void crawl() {
    print('crawling');
  }
}

abstract class AirborneInsect extends Insect with Fluttering {
  void buzz() {
    print('buzzing annoyingly');
  }
}

class Mosquito extends AirborneInsect {
  void doMosquitoThing() {
    crawl();
    flutter();
    buzz();
    print('sucking blood');
  }
}

abstract class Bird with Fluttering {
  void chirp() {
    print('chirp chirp');
  }
}

class Swallow extends Bird {
  void doSwallowThing() {
    chirp();
    flutter();
    print('eating a mosquito');
  }
}

複製代碼

也能夠在一個類上面使用多個mixin。若是須要在Bird類上用一個chirping mixn的話,就和Fluttering mixin一塊兒用就好。

abstract class Bird with Fluttering, Chirping 複製代碼

限制Mixin的使用

有的時候你不想讓mixin用在早已存在的類上面,你只是想讓它用在某些特定的類或者其子類上。這一般你的代碼對早已存在的代碼有依賴。

在野生動物app這個例子裏,你發現僅僅支持swallow已經不夠了。還有其餘種類的鳥好比麻雀或者Blue Jay等。與麻雀不一樣,不少其餘的鳥須要從地裏面啄食,種子啊,蟲子啊的。。。

Bird抽象類添加方法是不可能的,由於不是全部的鳥都須要啄食。因此,爲了不代碼冗餘,你能夠建立一個叫作Pecking的mixin。

mixin Pecking {
  void peck() {
    print('pecking');
  }
}
複製代碼

這至少比代碼榮譽好不少了。可是,也會有人把這個mixin用在Insect類上。這樣使用mixin問題就大了。

當你開始研究一個鳥類的動做的時候,你會發現鳥兒在逐出食物以後就會發出愉悅的鳥鳴。從當前的mixin裏面調用chirp方法是不可能的。要改也很是簡單,只要告訴Dart,Pecking mixin只能用在Bird類上面。如今調用Bird類的方法就沒有問題了。

//...
mixin Pecking on Bird {
    void peck() {
        print('pecking');
        chirp();
    }
}

class Sparrow extends Bird with Pecking {}

class BlueJay extends Bird with Pecking {}
複製代碼

結論

Mixin對於繼承體系中避免代碼的冗餘很是有用處。mixin也能夠被約束在只能夠用在某些特定的類上面,這讓他們成爲了開發的一大利器!

相關文章
相關標籤/搜索