最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

第 41 講:面向?qū)ο缶幊蹋ㄊ航涌诘亩鄳B(tài)

2021-05-21 07:58 作者:SunnieShine  | 我要投稿

前面我們講過了多態(tài),不過是針對于類的。在我們講了接口之后,接口實際上也可以多態(tài)。

Part 1 引例

假設(shè)我們邀請一群會吃飯的小伙伴參加比賽,然后角逐選出最強的一位參賽選手作為冠軍。那么我們就需要書寫一個方法,大概是這樣的:

注意我們這里,需要傳入一系列的會吃飯的小伙伴。如果我們在這里寫的是 Animal[] 的話,因為有些小伙伴不一定“會吃飯”(有 Eat 方法),那么我們就無法通過 Animal[] 來完成這個任務(wù)。

最合適的辦法,那肯定是用 IFoodie[] 來完成。返回值呢?第一名唄。那為什么不返回 Animal 類型而還是用 IFoodie 呢?并不是從 Animal 類派生的才可以實現(xiàn) IFoodie 接口。豬籠草就不能參賽了么?豬籠草也會吃東西,對吧??赡苣銌栁遥i籠草也不是動物了啊。你看我這個引例給的假設(shè),我可沒有說“只能是動物參賽”。

那么,總的來說,我們使用接口類型來表示“能做什么事情”的實例,來參與計算。

可是,我們怎么傳參進去呢?還記得類的多態(tài)嗎?類的多態(tài)是通過從某個類派生而產(chǎn)生的。那么,這里我們也可以這么做:

這就是所謂的接口的多態(tài)。我們使用實例化語句來產(chǎn)生一個實例,但用的是 IFoodie 接口來接收,因為它們都實現(xiàn)了 IFoodie 接口。

這個 pitcherPlant 是豬籠草。

Part 2 接口類型多態(tài)的用法

我們把這些類型都用接口類型來接收了,可這樣做的好處是什么呢?

還記得 IFoodie 這個接口類型里有什么東西嗎?是的,只有一個 Eat 方法。換句話說,如果我們將某個實例賦值給一個 IFoodie 類型(假設(shè)這種賦值是成功的的話),那么后續(xù)在使用這個變量的時候,你只能寫出 .Eat() 的東西出來,別的都不行。因為這個接口只有這個成員。

假設(shè)我們這里的 IFoodie 接口里的 Eat 方法返回一個 int 類型結(jié)果,表示這個吃貨在等同時間里吃了多少東西進去,那么我們?nèi)〕鲎畲笾底鳛榻Y(jié)果,然后把吃得最多的這個對象給返回出來??梢钥吹剑覀冎恍枰粋€ Eat 方法,別的方法也用不上,所以直接這么書寫就是合適的。

Part 3 接口的隱式和顯式轉(zhuǎn)換

和類的繼承一致,接口雖然換了個說法,叫做“實現(xiàn)”,但是實際上本身還是繼承的語法和機制。所以,它和類的強制和隱式轉(zhuǎn)換也是一樣的規(guī)則:

  • 如果從子類型轉(zhuǎn)基接口的話,因為是一定可以轉(zhuǎn)換成功的,因此是隱式轉(zhuǎn)換的;

  • 如果從基接口轉(zhuǎn)子類型的話,因為類型不一定成功轉(zhuǎn)換,因此是使用強制轉(zhuǎn)換的。

想必具體我就不用說明了吧。比如前面的 IFoodie 作為接收方,而等號右側(cè)是那些類型的實體。因為這些類型都是實現(xiàn)了 IFoodie 類型的接口的,所以這樣的賦值是隱式轉(zhuǎn)換的。

3-1 isas,以及轉(zhuǎn)換運算符

和類的多態(tài)一樣,因為類可以通過別的類(父類)來表達出來,因此它可以達到多態(tài)的形式。那么,如果是“大轉(zhuǎn)小”的話,需要用強制轉(zhuǎn)換;而如果是“小轉(zhuǎn)大”的話,直接是隱式轉(zhuǎn)換。這里的“大”和“小”指的是這個類型可以適用的類型的范圍。顯然,抽象類用來給子類繼承,那么抽象類的范圍應(yīng)該是更大的。

接口也是一樣的。如果我們要把類型賦值給自己實現(xiàn)了的某個接口類型,那么自然是隱式轉(zhuǎn)換的。因為接口類型可以表達的數(shù)據(jù)類型更多,畢竟非常多的類型都可以實現(xiàn)接口,但類本身只有一個。

那么反過來,如果要把接口轉(zhuǎn)換回普通的類的話,就拿 IFoodie 來說,既然 Dog、Cat 這些類型全都實現(xiàn)了 IFoodie 接口,那么反過來我們就無法確定,一個 IFoodie 接口真正表達的是什么數(shù)據(jù),因此我們需要使用強制轉(zhuǎn)換。如果轉(zhuǎn)換失敗,那么必然就會產(chǎn)生錯誤。此時我們依然需要使用 is 或者 as 運算符來判別其類型。

或者是

比如這樣的形式。

3-2 無法對接口使用自定義類型轉(zhuǎn)換器

如題,我們無法在一個類里書寫類似這樣的代碼:

這樣在 C# 里直接就是不允許的。你有想過為什么嗎?原因其實很簡單,因為類型本身是它實現(xiàn)的那些接口決定的。如果你自定義實現(xiàn)類型轉(zhuǎn)換的話,就破壞了這種轉(zhuǎn)換的體系架構(gòu)。比如我 dog 對象是 Dog 這個類型的,它實現(xiàn)了 IRunnable、IFoodie 或者別的什么接口,那么我們自然而然就知道,這些接口類型都是 dog 可以轉(zhuǎn)換過去的接口類型;但是,我假設(shè)有一個 ICanSaySomething 的接口來表示“能說話”(注意接口名稱前面的 I 一定是 interface 這個單詞的縮寫,而不是指的“我”),顯然狗狗是不能說話的,因此無法對狗狗實現(xiàn)這個接口。

那么既然狗狗無法實現(xiàn)這個接口,就必然不可能允許狗狗往 ICanSaySomething 接口上轉(zhuǎn)換。如果 C# 允許你自定義這樣的轉(zhuǎn)換的話,顯然就破壞了 C# 面向?qū)ο蟮念愋娃D(zhuǎn)換系統(tǒng),因此會導致不穩(wěn)定。

Part 4 沒了?

是的,接口的多態(tài)基本上和類的多態(tài)是一樣的寫法,所以也沒有什么特別需要講的東西。

至此,面向?qū)ο蟮膬?nèi)容我們就介紹到這里。下一節(jié)我們講開始新的篇章。


第 41 講:面向?qū)ο缶幊蹋ㄊ航涌诘亩鄳B(tài)的評論 (共 條)

分享到微博請遵守國家法律
周至县| 密山市| 西畴县| 余江县| 扎赉特旗| 家居| 阜新市| 西华县| 崇义县| 八宿县| 慈溪市| 屯门区| 宣城市| 库尔勒市| 拉孜县| 平江县| 卢氏县| 离岛区| 邢台市| 桂东县| 黑河市| 松溪县| 汉寿县| 天峻县| 崇礼县| 永春县| 木里| 壶关县| 深水埗区| 石景山区| 襄汾县| 黄浦区| 齐齐哈尔市| 白沙| 淳安县| 同德县| 黄大仙区| 浑源县| 厦门市| 凤山县| 宜州市|