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

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

第 37 講:面向?qū)ο缶幊蹋ň牛撼蓡T繼承控制

2021-05-14 08:17 作者:SunnieShine  | 我要投稿

前面我們講了繼承控制的基本使用方式和手段,今天我們來(lái)說(shuō)一下,跟成員有關(guān)系的繼承控制方式,以及對(duì)應(yīng)的關(guān)鍵字。

Part 1 abstractoverride 成員修飾符

前面我們說(shuō)到 abstract 類(lèi)修飾符,表示類(lèi)不再允許實(shí)例化,使用 new 語(yǔ)句產(chǎn)生這個(gè)類(lèi)型的對(duì)象??蓡?wèn)題在于,以類(lèi)為單位控制的繼承實(shí)在是沒(méi)有多大的用途。下面我們來(lái)介紹 abstract 修飾符修飾的成員。

在抽象類(lèi)(abstract class 組合)里,有一種特殊的成員類(lèi)別,叫抽象成員。這是別的類(lèi)型不具備的修飾方式。我們可直接在抽象類(lèi)里,對(duì)某個(gè)或某些成員追加 abstract 修飾符,以表達(dá)這個(gè)成員“我這個(gè)類(lèi)不給實(shí)現(xiàn)邏輯”;而具體的實(shí)現(xiàn)邏輯丟給派生類(lèi)。

這個(gè)思維是我們第一次聽(tīng)說(shuō),因此我們來(lái)舉例說(shuō)明。假設(shè)我有一個(gè) Shape 的抽象類(lèi),表示一個(gè)形狀。顯然,形狀肯定會(huì)有一些相關(guān)的屬性信息,比如說(shuō)形狀本身的面積。假設(shè)我們定為 Area。那么我們創(chuàng)建一些子類(lèi)型,從 Shape 類(lèi)型派生。

我們創(chuàng)建了兩個(gè)子類(lèi)型 SquareCircle 類(lèi)型,從 Shape 派生。在 Shape 里有一個(gè) Area 屬性??梢宰⒁庹Z(yǔ)法不是很好理解的地方在于這個(gè) get 后直接跟了一個(gè)分號(hào)。這是正確的寫(xiě)法,是因?yàn)檫@個(gè) Areaget 方法(取值器)目前是無(wú)法寫(xiě)出來(lái)的,因?yàn)槲叶疾恢肋@個(gè) Shape 到底需要什么信息才可計(jì)算面積。比如正方形需要一個(gè)參數(shù)(邊長(zhǎng))就可以計(jì)算面積;但長(zhǎng)方形需要兩個(gè)參數(shù)(長(zhǎng)和寬)才可以計(jì)算;梯形則需要三個(gè)參數(shù)(上底、下底和高)。

因?yàn)閰?shù)不定,所以我們無(wú)法從基類(lèi)型 Shape 上給出代碼實(shí)現(xiàn)。于是,我們定成抽象屬性,以表達(dá)這個(gè)屬性只能且必須在子類(lèi)型是實(shí)現(xiàn)。

在子類(lèi)型 SquareCircle 里,我們不得不對(duì) Area 給出實(shí)現(xiàn)的代碼。另外,我們要對(duì)上面的抽象類(lèi)型的 Area 屬性實(shí)現(xiàn)執(zhí)行代碼,因此我們需要在這個(gè)屬性前面追加 override 關(guān)鍵字。override 專(zhuān)門(mén)用來(lái)表達(dá)“我是把基類(lèi)型的同名成員拿來(lái)使用和修改的”,在一般情況上是不使用這個(gè)關(guān)鍵字的。

const 修飾符可修飾一個(gè)系統(tǒng)自帶的那些數(shù)據(jù)類(lèi)型的字面量。它和 readonly 目前的唯一區(qū)別是,const 只能修飾一個(gè)字面量賦值過(guò)來(lái)的字段,且不能修飾 static 修飾符;而 readonly 可以修飾任何數(shù)據(jù)類(lèi)型賦值過(guò)來(lái)的字段,且可以有 static 也可以沒(méi)有 static

Part 2 sealedoverride 成員修飾符

正相反的是,如果類(lèi)型給出了實(shí)現(xiàn),那么就需要用 override 修飾符對(duì)成員進(jìn)行修飾。但是,override 修飾后的成員還可繼續(xù)在往下繼承的類(lèi)型里被重寫(xiě)和修改邏輯。比如說(shuō) A 類(lèi)型有個(gè) Prop 屬性,是 abstract 修飾的;接著 BA 類(lèi)型派生,那么 Prop 屬性在 B 類(lèi)型里就必須重寫(xiě)和修改邏輯,因此要標(biāo)記 override 修飾符??衫^承是可以不限制的,所以如果還有個(gè) C 類(lèi)型走 B 類(lèi)型派生的話,那么 C 類(lèi)型里也可重寫(xiě) B 類(lèi)型里的 Prop 的實(shí)現(xiàn)邏輯。

假設(shè) B 類(lèi)型給出的實(shí)現(xiàn)不可變動(dòng),不讓后續(xù)繼承的時(shí)候修改的話,我們可使用 sealed 關(guān)鍵字標(biāo)記這個(gè)成員(構(gòu)成 sealed override 的關(guān)鍵字組合),來(lái)表達(dá)這個(gè)成員是重寫(xiě)的,但在這里重寫(xiě)后,后續(xù)只能使用這個(gè)成員,而不可修改執(zhí)行邏輯。

比如這樣寫(xiě)代碼的話,C 類(lèi)型里給出 Prop 的實(shí)現(xiàn),因?yàn)?CB 類(lèi)型派生,但 B 類(lèi)型里 Prop 屬性就標(biāo)記了 sealed 關(guān)鍵字了,因此這個(gè)成員不再允許后續(xù)繼承的時(shí)候再次重寫(xiě)了,所以 C 類(lèi)型里 Prop 的屬性就會(huì)產(chǎn)生編譯器錯(cuò)誤,編譯器會(huì)提示你“不能這么用”。

Part 3 virtualoverride 成員修飾符

abstract 的好處在于,可以把成員作為單位提供抽象的書(shū)寫(xiě)模式,編譯器就會(huì)自動(dòng)提示我們讓我們?cè)谧宇?lèi)型里實(shí)現(xiàn)它們,不論對(duì)于代碼實(shí)現(xiàn)來(lái)說(shuō),還是代碼書(shū)寫(xiě)來(lái)說(shuō),都非常方便。但是,abstract 有一個(gè)問(wèn)題是,如果我基類(lèi)型想要給出默認(rèn)的實(shí)現(xiàn)代碼的話(而不是一定非要丟給派生類(lèi)來(lái)實(shí)現(xiàn),我們可先給出一個(gè)默認(rèn)實(shí)現(xiàn),然后派生類(lèi)按自己是否需要修改來(lái)決定到底需不需要 override 重寫(xiě)和修改掉原始的邏輯)。

比如說(shuō)前面舉的例子 Car(汽車(chē))類(lèi)型和 ConvertibleCar(敞篷跑車(chē))類(lèi)型。我們顯然可以給 Car 提供一個(gè)默認(rèn)的實(shí)現(xiàn)代碼來(lái)輸出汽車(chē)的具體描述。

這樣寫(xiě)肯定是沒(méi)錯(cuò)的,但問(wèn)題就在于這里的 new 關(guān)鍵字改變了繼承的關(guān)系。new 關(guān)鍵字是表示“我子類(lèi)型里提供一個(gè)同名的方法,而這個(gè)方法和基類(lèi)型的那個(gè)方法沒(méi)有任何關(guān)系”。這怎么可能?基類(lèi)型的 GetDescription 顯然是照搬下來(lái)并重新修改邏輯才對(duì)。因此,我們這里必須改用 override 修飾符。

問(wèn)題來(lái)了?;?lèi)型的 GetDescription 成員并沒(méi)有修飾 abstract,因?yàn)樗旧砭褪亲詭Я藞?zhí)行的邏輯的,如果我們給子類(lèi)型的 GetDescription 方法標(biāo)記 override 這不就是錯(cuò)了么。

那么,怎么解決兩邊都沒(méi)辦法解決的問(wèn)題呢?我們只需要在基類(lèi)型 Car 里的 GetDescription 方法上標(biāo)記 virtual,以表達(dá)“這個(gè)方法可提供給派生類(lèi)型重寫(xiě)和修改邏輯”。

這樣的話,基類(lèi)型 Car 里的 GetDescription 方法就表示“我有自己的實(shí)現(xiàn)代碼,你可以用也可以修改邏輯”。如果你需要修改執(zhí)行代碼的話,這里你需要為子類(lèi)型重寫(xiě)的這個(gè)同名方法 GetDescription 上追加 override 修飾符,來(lái)表示“我是確確實(shí)實(shí)是從基類(lèi)型里拿下來(lái)的成員,且要修改執(zhí)行邏輯的”。

Part 4 使用 base 對(duì)象調(diào)用基類(lèi)型成員的執(zhí)行邏輯

假設(shè)一種情況。我這里有兩個(gè)類(lèi),一個(gè)叫做 Person,表示一個(gè)人,而另外有一個(gè)類(lèi)叫 Employee 類(lèi),表示雇員(社會(huì)人)。

那么,請(qǐng)注意最下面的 Main 方法,執(zhí)行了 e 實(shí)例(Employee 類(lèi)型的實(shí)例)的 GetInfo 方法,會(huì)輸出什么呢?

我們定位到 Employee 里面的 GetInfo 方法上去。里面寫(xiě)了一句 base.GetInfo(),還記得之前說(shuō)過(guò)的 base 關(guān)鍵字嗎?是的,base 關(guān)鍵字用來(lái)表示基類(lèi)型的成員的使用。但是因?yàn)榍懊鏇](méi)有提到繼承的控制,因此 basethis 的效果是一樣的。不過(guò)這里不一樣的地方是,因?yàn)?GetInfo 是被重寫(xiě)過(guò)的,因此寫(xiě)的 base.GetInfo() 一定指的是基類(lèi)型的那個(gè) GetInfo。因此,這句話等效于把基類(lèi)型的 GetInfo 的執(zhí)行代碼直接給抄下來(lái)。

因此,整體輸出三句話:第一個(gè)是輸出 name,第二個(gè)是輸出 ssn,最后是重寫(xiě)的 GetInfo 方法里輸出的 id。

Part 5 一些問(wèn)題

下面針對(duì)于前文介紹和的內(nèi)容,給出一些可能你有疑惑的問(wèn)題。

5-1 abstract、sealedvirtual 修飾符的適用范圍

顯然,并非所有成員都可以修飾這些東西。比如說(shuō)字段。字段并不是一種執(zhí)行邏輯,而是一個(gè)數(shù)值。而 static 修飾過(guò)的成員也都不能使用這些關(guān)鍵字。因?yàn)槔^承機(jī)制顯然是跟對(duì)象綁定起來(lái)才有意義。比如,“工人”和“老師”可能不是同一個(gè)類(lèi)型的實(shí)例,比如有可能“工人”是 Worker 類(lèi)型的,而“老師”則可能是 Teacher 類(lèi)型的。但是,它們倆都從 Person 類(lèi)型派生下來(lái),這個(gè) Person 類(lèi)型可能包含了一些可以使用的成員,比如 Eat 方法表示吃飯過(guò)程;Sleep 方法表示睡覺(jué)過(guò)程;GoShopping 表示購(gòu)物血拼的過(guò)程。但是,如果是靜態(tài)的成員的話,這一切就顯得沒(méi)有意義。因?yàn)殪o態(tài)的話,并不會(huì)在邏輯上跟一個(gè)單獨(dú)的對(duì)象綁定起來(lái),此時(shí)說(shuō)什么吃飯購(gòu)物都顯得沒(méi)有了意義,那你還抽象、重寫(xiě)它們干什么呢?

因此,這三個(gè)修飾符的適用范圍顯然是:

  • 不能是字段;

  • 不能被 static 修飾符過(guò)的成員。

5-2 overridenew 的區(qū)別

可以看到,前面三個(gè)小節(jié)分別說(shuō)的是 abstract、sealedvirtual 關(guān)鍵字,但因?yàn)樗鼈兌伎纱钆?override 關(guān)鍵字一并使用,所以標(biāo)題里全都帶有 override 修飾符這個(gè)東西。而前面我們也說(shuō)了 new 修飾符。由于它們倆的功能看起來(lái)差不太多,所以下面我們來(lái)說(shuō)一下這兩個(gè)關(guān)鍵字的區(qū)別。

  • override 修飾符:這個(gè)成員是我從基類(lèi)型拿下來(lái)的同名成員,因此我這里是用來(lái)修改原始類(lèi)型成員的一種機(jī)制;

  • new 修飾符:這個(gè)成員和基類(lèi)型成員的實(shí)現(xiàn)沒(méi)有半點(diǎn)關(guān)系。我這里給出的實(shí)現(xiàn)會(huì)讓基類(lèi)型這個(gè)成員完全被覆蓋掉,阻斷了這個(gè)成員在整個(gè)繼承鏈上的繼承情況。

要知道,繼承關(guān)系是可無(wú)限往下的,A 可以派生出 B,然后 B 還能派生出 C,甚至 C 還能派生出 D 類(lèi)型。如果在 B 類(lèi)型里用到 override 關(guān)鍵字修飾了某個(gè)成員,就表達(dá) B 是重寫(xiě)了 A 的這個(gè)成員,修改掉了里面的邏輯;但是如果 B 類(lèi)型某個(gè)成員用的是 new 關(guān)鍵字,那么 A 類(lèi)型的這個(gè)同名成員和 B 這個(gè)成員一點(diǎn)關(guān)系都沒(méi)有了。以后,CD 類(lèi)型里的這個(gè)成員都以 B 這個(gè)成員為準(zhǔn),而 A 里的同名成員被 B 類(lèi)型用 new 修飾符覆蓋掉了。


第 37 講:面向?qū)ο缶幊蹋ň牛撼蓡T繼承控制的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
阿合奇县| 松潘县| 缙云县| 垫江县| 丘北县| 灌阳县| 贡嘎县| 苏尼特右旗| 洛阳市| 楚雄市| 运城市| 海伦市| 柏乡县| 浮山县| 济南市| 溧水县| 天峻县| 阜阳市| 武安市| 临漳县| 师宗县| 昌宁县| 彝良县| 察雅县| 双桥区| 贵港市| 日土县| 通道| 扶风县| 怀仁县| 墨江| 搜索| 修文县| 巴楚县| 乐至县| 襄垣县| 吉林市| 遵化市| 沐川县| 南丰县| 南木林县|