【JS】602- Mixin!這是做什麼的,如何使用?

本文轉載於 SegmentFault 社區

作者:小紅星閃啊閃

這裏補充一下Mixin的定義:


只要一個類是繼承自Object的而且沒有定義構造方法,那麼這個類可以是一個Mixin了。當然,如果你想讓mixin的定義更加的清晰,可以使用mixin關鍵字開頭來定義。具體請參考這裏

原文截圖體會一下風格。



正文

在經典的面向對象編程語言裏一定會有常規的類,抽象類和接口。當然,Dart也有它自己的接口,不過那是另外的文章要說的。有的時候陰影裏潛伏者另外的野獸:Mixin!這是做什麼的,如何使用?我們來一起發現。




沒有mixin的世界

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

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類(就是一種可以吃掉整個蚊子的東西)

同樣的也有很多鳥類共有的東西,我們可以創建一個Bird類。這個時候問題就出現了 -- 鳥也會振動翅膀!但是,你沒法把flutter方法從AirboneInsect類裏面提取出來組成一個新的類Fluttering。

爲什麼?Bird類可以繼承Fluttering類,但是AirboneInsect不可以,它已經繼承了Insect類了。Dart可不支持多繼承(真很好)

這下,你需要給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非常的簡單:

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也可以被約束在只可以用在某些特定的類上面,這讓他們成爲了開發的一大利器!

參考鏈接:

https://resocoder.com/2019/07/21/mixins-in-dart-understand-dart-flutter-fundamentals-tutorial/

原創系列推薦

1. JavaScript 重溫系列(22篇全)

2. ECMAScript 重溫系列(10篇全)

3. JavaScript設計模式 重溫系列(9篇全)

4. 正則 / 框架 / 算法等 重溫系列(16篇全)

5. Webpack4 入門(上)|| Webpack4 入門(下)

6. MobX 入門(上) ||  MobX 入門(下)

7. 59篇原創系列彙總

回覆“加羣”與大佬們一起交流學習~

點這,與大家一起分享本文吧~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章