Flutter 中 Dart的Mixin示例詳解
原文在這里。寫(xiě)的不錯(cuò),推薦各位看原文。
這里補(bǔ)充一下Mixin的定義:
只要一個(gè)類(lèi)是繼承自Object的而且沒(méi)有定義構(gòu)造方法,那么這個(gè)類(lèi)可以是一個(gè)Mixin了。當(dāng)然,如果你想讓mixin的定義更加的清晰,可以使用mixin關(guān)鍵字開(kāi)頭來(lái)定義。具體請(qǐng)參考這里
原文截圖體會(huì)一下風(fēng)格。

正文
在經(jīng)典的面向?qū)ο缶幊陶Z(yǔ)言里一定會(huì)有常規(guī)的類(lèi),抽象類(lèi)和接口。當(dāng)然,Dart也有它自己的接口,不過(guò)那是另外的文章要說(shuō)的。有的時(shí)候陰影里潛伏者另外的野獸:Mixin!這是做什么的,如何使用?我們來(lái)一起發(fā)現(xiàn)。
沒(méi)有mixin的世界
假設(shè)你在構(gòu)建一個(gè)模擬野生動(dòng)物的app,那么你需要一個(gè)Mosquito(蚊子)類(lèi)。作為一個(gè)有預(yù)見(jiàn)性的開(kāi)發(fā)人員,你會(huì)抽象蚊子們有的共通的東西然后放在一個(gè)抽象類(lèi)里。
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');
}
}
很棒!你已經(jīng)做到了!添加新的昆蟲(chóng)就如同微風(fēng)拂過(guò)一樣,根本不會(huì)有代碼的冗余出現(xiàn)。。。一直到你發(fā)現(xiàn)你需要一個(gè)Swallow類(lèi)(就是一種可以吃掉整個(gè)蚊子的東西)。
同樣的也有很多鳥(niǎo)類(lèi)共有的東西,我們可以創(chuàng)建一個(gè)Bird類(lèi)。這個(gè)時(shí)候問(wèn)題就出現(xiàn)了 -- 鳥(niǎo)也會(huì)振動(dòng)翅膀!但是,你沒(méi)法把flutter方法從AirboneInsect類(lèi)里面提取出來(lái)組成一個(gè)新的類(lèi)Fluttering。
為什么?Bird類(lèi)可以繼承Fluttering類(lèi),但是AirboneInsect不可以,它已經(jīng)繼承了Insect類(lèi)了。Dart可不支持多繼承(真很好)。
這下,你需要給Bird類(lèi)添加一個(gè)flutter方法了。代碼冗余發(fā)生了!
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的定義是“一種把類(lèi)代碼用在多個(gè)繼承樹(shù)的方法”。簡(jiǎn)單的說(shuō),mixin讓你不用繼承就可以引入代碼塊的方法。聲明一個(gè)mixin非常的簡(jiǎn)單:
mixin Fluttering {
void flutter() {
pring('fluttering');
}
}
這個(gè)mixin可以用在常規(guī)的類(lèi)上面也可以用在抽象類(lèi),只需要一個(gè)with關(guān)鍵字。在野生動(dòng)物模擬app例子里,你也許要用在抽象類(lèi)上了。
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');
}
}
也可以在一個(gè)類(lèi)上面使用多個(gè)mixin。如果需要在Bird類(lèi)上用一個(gè)chirping mixn的話(huà),就和Fluttering mixin一起用就好。
abstract class Bird with Fluttering, Chirping
限制Mixin的使用
有的時(shí)候你不想讓mixin用在早已存在的類(lèi)上面,你只是想讓它用在某些特定的類(lèi)或者其子類(lèi)上。這通常你的代碼對(duì)早已存在的代碼有依賴(lài)。
在野生動(dòng)物app這個(gè)例子里,你發(fā)現(xiàn)僅僅支持swallow已經(jīng)不夠了。還有其他種類(lèi)的鳥(niǎo)比如麻雀或者Blue Jay等。與麻雀不同,很多其他的鳥(niǎo)需要從地里面啄食,種子啊,蟲(chóng)子啊的。。。
給Bird抽象類(lèi)添加方法是不可能的,因?yàn)椴皇撬械镍B(niǎo)都需要啄食。所以,為了避免代碼冗余,你可以創(chuàng)建一個(gè)叫做Pecking的mixin。
mixin Pecking {
void peck() {
print('pecking');
}
}
這至少比代碼榮譽(yù)好很多了。但是,也會(huì)有人把這個(gè)mixin用在Insect類(lèi)上。這樣使用mixin問(wèn)題就大了。
當(dāng)你開(kāi)始研究一個(gè)鳥(niǎo)類(lèi)的動(dòng)作的時(shí)候,你會(huì)發(fā)現(xiàn)鳥(niǎo)兒在逐出食物之后就會(huì)發(fā)出愉悅的鳥(niǎo)鳴。從當(dāng)前的mixin里面調(diào)用chirp方法是不可能的。要改也非常簡(jiǎn)單,只要告訴Dart,Pecking mixin只能用在Bird類(lèi)上面?,F(xiàn)在調(diào)用Bird類(lèi)的方法就沒(méi)有問(wèn)題了。
//...
mixin Pecking on Bird {
void peck() {
print('pecking');
chirp();
}
}
class Sparrow extends Bird with Pecking {}
class BlueJay extends Bird with Pecking {}
結(jié)論
Mixin對(duì)于繼承體系中避免代碼的冗余非常有用處。mixin也可以被約束在只可以用在某些特定的類(lèi)上面,這讓他們成為了開(kāi)發(fā)的一大利器!
ps:下面在看下Flutter/Dart mixin類(lèi)的理解
mixin是將一些有共同特性的類(lèi)抽出來(lái)共用,把具體的特性封裝成一個(gè)mixin供其他類(lèi)使用。本質(zhì)上是為了減少代碼冗余。而implement也能實(shí)現(xiàn)這種功能,但是繼承自implement的子類(lèi)需要完全重寫(xiě)父類(lèi)的所有屬性與方法,這就造成了很多不必要的代碼冗余。
mixin在使用上有如下特點(diǎn):
mixin在定義時(shí)可以使用on關(guān)鍵字指定使用范圍
mixin swim on fish {
//具體實(shí)現(xiàn)
}
當(dāng)多個(gè)mixin函數(shù)一樣時(shí),后一個(gè)mixin會(huì)覆蓋前面一個(gè)(線(xiàn)性特征)
class S {
fun()=>print('A');
}
mixin MA {
fun()=>print('MA');
}
mixin MB {
fun()=>print('MB');
}
class A extends S with MA,MB {}
class B extends S with MB,MA {}
======
main() {
A a = A();
a.fun();
B b = B();
b.fun();
}
=====
MB
MA
mixin可以實(shí)現(xiàn)蕾絲多重繼承的功能,但是多重繼承中相同函數(shù)執(zhí)行并不會(huì)存在父子關(guān)系- mixin實(shí)現(xiàn)了一條繼承鏈,聲明的順序代表了繼承的順序,聲明在后面的
mixin會(huì)最先執(zhí)行 - 而最終的子類(lèi)與該繼承鏈上所有類(lèi)的類(lèi)型(
runtimeType)都能匹配上,即子類(lèi)擁有所有mixin類(lèi)的特性。
到此這篇關(guān)于Flutter 中 Dart的Mixin示例詳解的文章就介紹到這了,更多相關(guān)Flutter Dart的Mixin內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)QQ登錄界面遇到問(wèn)題及解決方法
本文給大家介紹android仿qq登錄界面的實(shí)現(xiàn)代碼,在實(shí)現(xiàn)此功能過(guò)程中遇到各種問(wèn)題,但是最終都順利解決,如果大家對(duì)android qq登錄界面實(shí)現(xiàn)方法感興趣的朋友一起學(xué)習(xí)吧2016-09-09
基于Android實(shí)現(xiàn)百度地圖定位過(guò)程詳解
這篇文章主要介紹了基于Android實(shí)現(xiàn)百度地圖定位過(guò)程詳解,需要的朋友可以參考下2015-11-11
Android Camera實(shí)現(xiàn)毫秒級(jí)拍照實(shí)例
本篇文章主要介紹了Android Camera實(shí)現(xiàn)毫秒級(jí)拍照實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-06-06
Android實(shí)現(xiàn)底部狀態(tài)欄切換的兩種方式
這篇文章主要介紹了Android實(shí)現(xiàn)底部狀態(tài)欄切換功能,在文中給大家提到了兩種實(shí)現(xiàn)方式,本文分步驟給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-06-06
Android如何監(jiān)測(cè)文件夾內(nèi)容變化詳解
最近在開(kāi)發(fā)android應(yīng)用程序的時(shí)候遇到了一個(gè)監(jiān)測(cè)文件夾的功能,所以下面這篇文章主要給大家介紹了關(guān)于Android如何監(jiān)測(cè)文件夾內(nèi)容變化的相關(guān)資料,需要的朋友可以參考下2021-12-12
Android實(shí)現(xiàn)錄音監(jiān)聽(tīng)動(dòng)畫(huà)的示例代碼
在很多app種內(nèi)置了語(yǔ)音助手,也存在各種動(dòng)畫(huà),這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)錄音監(jiān)聽(tīng)動(dòng)畫(huà)的示例代碼,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12
Android中模仿抖音加載框之兩顆小球轉(zhuǎn)動(dòng)效果
這篇文章主要介紹了Android仿抖音加載框之兩顆小球轉(zhuǎn)動(dòng)控件,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09
分享實(shí)現(xiàn)Android圖片選擇的兩種方式
本文給大家分享的是Android選擇圖片的兩種方式的實(shí)現(xiàn)代碼,分別是單張選取和多張批量選取,非常的實(shí)用,有需要的小伙伴可以參考下2016-01-01
Android實(shí)現(xiàn)一個(gè)比相冊(cè)更高大上的左右滑動(dòng)特效(附源碼)
這篇文章主要介紹了Android實(shí)現(xiàn)一個(gè)比相冊(cè)更高大上的左右滑動(dòng)特效(附源碼),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02

