版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。http://www.itdecent.cn/p/405ba04ffbdc
轉(zhuǎn)載請(qǐng)標(biāo)明出處:
http://www.itdecent.cn/p/405ba04ffbdc
本文出自 AWeiLoveAndroid的博客
本文首發(fā)在公眾號(hào)Flutter那些事,未經(jīng)允許,嚴(yán)禁轉(zhuǎn)載。
前言
Flutter1.0穩(wěn)定版昨晚的終于發(fā)布了。我們?yōu)榇烁械礁吲d。對(duì)于開發(fā)者來說,有了穩(wěn)定版相當(dāng)于一個(gè)定心丸。本文主要介紹Fllutter1.0的一些功能和相關(guān)工具。
Flutter系列博文鏈接 ↓:
工具安裝:
Flutter基礎(chǔ)篇:
- 谷歌Flutter1.0正式版發(fā)布
- Flutter基礎(chǔ)篇(1)-- 跨平臺(tái)開發(fā)框架和工具集錦
- Flutter基礎(chǔ)篇(2)-- 老司機(jī)用一篇博客帶你快速熟悉Dart語法
- Flutter基礎(chǔ)篇(3)-- Flutter基礎(chǔ)全面詳解
- Flutter基礎(chǔ)篇(4)-- Flutter填坑全面總結(jié)
- Flutter基礎(chǔ)篇(5)-- Flutter代碼模板,解放雙手,提高開發(fā)效率必備
- Flutter基礎(chǔ)篇(6)-- 水平和垂直布局詳解
- Flutter基礎(chǔ)篇(7)-- Flutter更新錯(cuò)誤全面解決方案(圖文+視頻講解)
- Flutter基礎(chǔ)篇(8)-- Flutter for Web詳細(xì)介紹
- Flutter基礎(chǔ)篇(9)-- 手把手教你用Flutter實(shí)現(xiàn)Web頁面編寫
- Flutter1.9升級(jí)體驗(yàn)總結(jié)(Flutter Web 1.9最新版本填坑指南)
Flutter進(jìn)階篇:
- Flutter進(jìn)階篇(1)-- 手把手帶你快速上手調(diào)試Flutter項(xiàng)目
- Flutter進(jìn)階篇(2)-- Flutter路由詳解
- Flutter進(jìn)階篇(3)-- Flutter 的手勢(shì)(GestureDetector)分析詳解
- Flutter進(jìn)階篇(4)-- Flutter的Future異步詳解
- Flutter進(jìn)階篇(5)-- 使用Flutter創(chuàng)建插件詳解并發(fā)布到Pub庫
- Flutter進(jìn)階篇(6)-- PageStorageKey、PageStorageBucket和PageStorage使用詳解
- Flutter進(jìn)階篇(7)-- Flutter路由輕量級(jí)框架FRouter
Dart語法系列博文鏈接 ↓:
Dart語法基礎(chǔ)篇:
Dart語法進(jìn)階篇:
在面向?qū)ο蟮木幊陶Z言中,Mixin是包含供其他類使用的方法的類,而不必是其他類的父類。其他類如何訪問
Mixin的方法取決于語言。Mixin有時(shí)被描述為“包含的”而不是“繼承的”。
Mixins鼓勵(lì)代碼重用,并且可用于避免多重繼承可能導(dǎo)致的繼承歧義(菱形問題),或者用于解決語言中缺少對(duì)多重繼承的支持的問題。Mixin還可以被視為具有實(shí)現(xiàn)方法的接口。這個(gè)模式是執(zhí)行依賴倒置原則的一個(gè)例子。
一、繼承歧義
(一)定義
繼承歧義,也叫菱形問題,也叫做鉆石問題,或者有時(shí)被稱為致命的死亡鉆石。當(dāng)兩個(gè)B和C類繼承自A,D類繼承自B和C時(shí)產(chǎn)生歧義。如果A中有一個(gè)方法在B和C中已經(jīng)重寫,而D沒有重寫它,那么D繼承的方法的版本是B,還是C?
如下圖所示:

(二)繼承歧義的緩解
不同的編程語言有不同的方法來處理這些重復(fù)繼承的問題,這里列舉幾個(gè)用的比較多的語言。
| 語言 | 解決方案 |
|---|---|
| C++(底層、硬件、編解碼、算法等都用得到) | 默認(rèn)情況下,每個(gè)繼承路徑都是分開的,因此D對(duì)象實(shí)際上包含兩個(gè)獨(dú)立的a對(duì)象,并且必須正確限定a成員的使用。如果從A到B的繼承和從A到C的繼承都標(biāo)記為virtual(例如,class B:virtual public A),那么c++會(huì)特別注意只創(chuàng)建一個(gè)對(duì)象,并正確使用A的成員。如果虛擬繼承和非虛擬繼承是混合的,那么只有一個(gè)虛擬A,對(duì)于每個(gè)到A的非虛擬繼承路徑,都有一個(gè)非虛擬A。C++需要顯式地聲明要使用的特性是從哪個(gè)父類調(diào)用的(例如:Worker::Human.Age)。C++不支持顯式的重復(fù)繼承,因?yàn)闆]有辦法限定要使用哪個(gè)超類(例如:在一個(gè)派生列表[class Dog : public Animal, Animal]中出現(xiàn)一個(gè)類不止一次)。C++還允許通過虛擬繼承機(jī)制創(chuàng)建多個(gè)類的單個(gè)實(shí)例(例如:Worker::Human和Musician::Human將引用相同的對(duì)象)。 |
| Java8(服務(wù)端開發(fā)、Android開發(fā)) | Java 8在接口上引入默認(rèn)方法。如果A、B、C是接口,B、C可以為A的抽象方法提供不同的實(shí)現(xiàn),從而導(dǎo)致菱形問題。D類必須重新實(shí)現(xiàn)該方法(它的主體可以簡(jiǎn)單地將調(diào)用轉(zhuǎn)發(fā)給一個(gè)超類來實(shí)現(xiàn)),否則模糊將被拒絕作為編譯錯(cuò)誤。(在Java 8之前,Java不受鉆石問題風(fēng)險(xiǎn)的影響,因?yàn)樗恢С侄嘀乩^承。) |
| Go(可以用于區(qū)塊鏈有關(guān)) | 在編譯時(shí)防止鉆石問題。如果一個(gè)結(jié)構(gòu)體D嵌入兩種結(jié)構(gòu)體B和C(這兩個(gè)結(jié)構(gòu)體都有一個(gè)方法F()),從而滿足接口A,那么如果調(diào)用D.F(),或者如果D的實(shí)例被分配給類型A.B和C的變量,則編譯器將會(huì)提示ambiguous selector(模擬兩可的選擇)。 |
| Python(可以用于人工智能有關(guān)) | Python的繼承順序影響類語義。Python在引入新樣式的類時(shí)必須處理這個(gè)問題,所有這些類都有一個(gè)共同的祖先對(duì)象。Python使用C3線性化(或方法解析順序(Method Resolution Order,MRO))算法創(chuàng)建類列表。該算法強(qiáng)制執(zhí)行兩個(gè)約束:子類先于父類,如果一個(gè)類從多個(gè)類繼承,它們將按照基類元組中指定的順序保存(但是在這種情況下,繼承圖中較高的一些類可能先于圖中較低的類)。因此,方法的分辨率順序?yàn)?D, B, C, A。 |
| Scala(可以用于大數(shù)據(jù)方面) | Scala允許特性的多個(gè)實(shí)例化,通過在類層次結(jié)構(gòu)和特征層次結(jié)構(gòu)之間添加區(qū)別,可以實(shí)現(xiàn)多重繼承。類只能從單個(gè)類繼承,但是可以根據(jù)需要混合(mix-in)任意多的特性。Scala使用擴(kuò)展的traits的右優(yōu)先深度優(yōu)先的搜索來解析方法名,然后除去結(jié)果列表中每個(gè)模塊的最后一次出現(xiàn)。所以,解決的順序是[D, C, A, B, A],被減少到[D, C, B, A]
|
只允許單個(gè)繼承(類只能從一個(gè)基類派生)的語言沒有菱形問題。這樣做的原因是,無論方法的重復(fù)或位置如何,這些語言在繼承鏈的任何級(jí)別上最多只能實(shí)現(xiàn)一個(gè)方法。通常,這些語言允許類實(shí)現(xiàn)多個(gè)protocols,在Java中稱為接口。這些協(xié)議定義了方法,但沒有提供具體的實(shí)現(xiàn)。這個(gè)策略已經(jīng)被ActionScript、c#、D、Java、Nemerle、Object Pascal (Free Pascal and Delphi)、Objective-C、Smalltalk、Swift、PHP所使用。所有這些語言都允許類實(shí)現(xiàn)多個(gè)protocols。
此外,Ada、Objective-C、c#、Delphi/Free Pascal、Java、Swift、PHP等語言允許接口的多重繼承(在Objective-C和Swift中稱為protocols(協(xié)議))。接口就像抽象基類,它們指定方法簽名而不實(shí)現(xiàn)任何行為。(“純”接口,例如版本7之前的Java接口,不允許接口中的任何實(shí)現(xiàn)或?qū)嵗龜?shù)據(jù)。)然而,即使當(dāng)多個(gè)接口聲明相同的方法簽名時(shí),只要該方法在繼承鏈中的任何位置實(shí)現(xiàn)(定義),它就會(huì)覆蓋該方法在其上鏈中的任何實(shí)現(xiàn)(在它的超類中)。因此,在繼承鏈的任何給定級(jí)別上,任何方法最多只能有一個(gè)實(shí)現(xiàn)。因此,單繼承方法實(shí)現(xiàn)即使在接口的多繼承中也不存在菱形問題。隨著Java 8中接口的默認(rèn)實(shí)現(xiàn)的引入,仍然有可能生成菱形問題,盡管這只會(huì)作為編譯時(shí)錯(cuò)誤出現(xiàn)。
本文轉(zhuǎn)載自:https://en.wikipedia.org/wiki/Mixin#Programming_languages_that_use_mixins