白馬非馬----繼承(我還轉(zhuǎn))
發(fā)表時(shí)間:2023-07-30 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]白馬非馬 ----繼承作者:HolyFire古人云:“白馬非馬”,為何如是說(shuō)呢。這里有個(gè)講究,白馬是指一種白色的馬,而非馬里的馬指的是各種各樣的馬,有黑馬,棕嗎,五花馬等等,這是在顏色上有所區(qū)別,馬...
白馬非馬
----繼承
作者:HolyFire
古人云:“白馬非馬”,為何如是說(shuō)呢。
這里有個(gè)講究,白馬是指一種白色的馬,而非馬里的馬指的是各種各樣的馬,有黑馬,棕嗎,五花馬等等,這是在顏色上有所區(qū)別,馬還有產(chǎn)地,品種等等區(qū)別。這里給了我們一個(gè)啟示,各種各樣的馬可以找出很多共同點(diǎn),稱之為馬,符合這些特點(diǎn)的動(dòng)物就是馬了,所以這些共同點(diǎn)不能多也不能少,多了不能同用于所有的馬,少了表達(dá)不出馬來(lái)。要區(qū)別一只馬需要很多信息,比如一只黑色的蒙古馬,在這里,我除了描述一只馬外,還要指出它是黑色的,產(chǎn)地是蒙古,這里還沒(méi)有加上馬的品種。
我在《芥子須彌-----封裝》里曾經(jīng)提及,事物可以劃分成屬性和方法的集合。那么我們是不是可以對(duì)這個(gè)集合進(jìn)行再加工呢,我們只要在里面加上一點(diǎn)別的什么,那他就可以變成別的事物了,想象一下在馬的身上加上鹿的角,呵呵呵呵,可笑嗎。那么我們說(shuō)一些嚴(yán)肅的,知道我們中華民族的圖騰嗎,龍!龍是在蛇的頭上加上鹿的角,身上加上虎的腿腳,尾巴是魚的尾巴,等等。但是不是隨隨便便就能造就龍這樣偉大的象征的,不好好設(shè)計(jì),就會(huì)成為畫蛇添足。
雖然是簡(jiǎn)單和相加,但也是有不同的方式的。一般來(lái)說(shuō)有兩種方式:關(guān)聯(lián)和衍生。
關(guān)聯(lián):假設(shè)原來(lái)的類是用一個(gè)袋子將屬性和方法包起來(lái),那是用關(guān)聯(lián)描述了多個(gè)類之間的關(guān)系,最簡(jiǎn)單的情況就是用一個(gè)更大的袋子將兩個(gè)小袋子包起來(lái),成為一個(gè)新的類。這種關(guān)聯(lián)叫做組合。
衍生:衍生呢就是用一個(gè)大的袋子將一個(gè)小的袋子與一些屬性和方法包起來(lái),成為一個(gè)新的類
A
C
B
a:關(guān)聯(lián)
A
D
b:衍生
我還是用C++來(lái)表示一下
class A{
//...屬性+方法
};
class B{
//...屬性+方法
};
//關(guān)聯(lián)后的新類C
class C{
A a;
B b;
};
//衍生后的新類D
class D : public A{
//...屬性+方法
};
看起來(lái)關(guān)聯(lián)(組合)比較容易理解,即將類作為一個(gè)屬性,然后形成一個(gè)新的類,這和原來(lái)類的使用沒(méi)什么區(qū)別,自己定義的類就是一個(gè)類型,這正是封裝要做的。
衍生—在原來(lái)的類的基礎(chǔ)上加上一些屬性和方法產(chǎn)生一個(gè)新類,看起來(lái)新穎誘人,在面包上灑一些芝麻,吃起來(lái)更有香味,不是嗎。
如何好好利用這一方法,就是我要說(shuō)的----繼承,只要用心去做,面包也會(huì)非常美味。(這里提及的都是共有繼承也就是class Y: public X;的形式)
上面的方法說(shuō)起來(lái)簡(jiǎn)單,要是用好它,不是件容易的事。
首先D和A有相同的部分就是A
第二,D有A沒(méi)有的部分
光光這兩點(diǎn)還說(shuō)明不了繼承的用途
我們加上一個(gè)新類E,他也是與類A衍生得來(lái)的
class E : public A{
//...屬性+方法
};
這樣我們就清楚一點(diǎn)了,A是D和E的共同點(diǎn)
耶~~~~!我們終于發(fā)現(xiàn)這樣做的好處了。
類D和類E有相同的部分A,而這里A只被處理了一次,也就是說(shuō)我們可以少處理一個(gè)和A一模一樣的工作,如果有許多個(gè)類都是從A衍生而來(lái)的,那么我們就發(fā)達(dá)了,問(wèn)題是,如何讓更多的類可以與類A衍生得到有用并好用的類。
這里老祖宗又顯靈了,白馬非馬說(shuō)的就是這個(gè)道理,馬正是這個(gè)類A,加上顏色,產(chǎn)地,品種,就可以描述各種各樣的馬了,加上健康等信息還能說(shuō)明馬的狀態(tài),如一只活蹦亂跳的黑色蒙古馬。
在我們的知識(shí)里有很多已知的共同點(diǎn),碗,瓷器,風(fēng),人,花草,我們將他們成為統(tǒng)稱。
我們可以下一個(gè)定義了:繼承--就是將事物之間相同和相似的部分歸納出來(lái)。
我們來(lái)看一下基類A和子類D的關(guān)系,可以發(fā)現(xiàn)D中含有A,也就是說(shuō)可以從一個(gè)D類的對(duì)象中提取出一個(gè)A類的對(duì)象來(lái),這種現(xiàn)象就是繼承的向下性,馬可以是白馬,而白馬就不能說(shuō)成是馬這個(gè)種類的代表。表現(xiàn)在C++中如何處理呢。
D d;
A a = d;
這里將會(huì)產(chǎn)成一個(gè)A類型的臨時(shí)變量,它是由d中類A那部分組成的
[
d的組成
][類A的部分]--à臨時(shí)變量da;
…
]
A a = da;
這種現(xiàn)象叫做切片
再看另一種情況
D * d = new D;
A * a = d;
這時(shí)候A * a = d;只涉及到指針的賦值,沒(méi)有對(duì)象的創(chuàng)建,所以不會(huì)引起切片,這里是將d在內(nèi)存中的地址保存在a這個(gè)指針里,而描述指針指向的對(duì)象是一個(gè)類A的對(duì)象。由于,D中關(guān)聯(lián)A的信息,C++編譯器使得這樣的操作是合法的,也是可以理解的。
我們可以把繼承A的D稱作為A的某個(gè)類型,是類A的一種(或者說(shuō),D是一個(gè)A),就象白馬是一種馬一樣(白馬是一匹馬)。
繼承非常強(qiáng)大,使用它能得到很多好處,但是世界上沒(méi)有包治百病的,過(guò)分的運(yùn)用繼承也會(huì)帶來(lái)麻煩。可以看出繼承是一種靜態(tài)的關(guān)系,在編譯期間很多東西都定下來(lái)了,這也提高了效率,但是要改變很困難,所以靈活性還不夠,要想清楚,你的目的是什么,再?zèng)Q定使用關(guān)聯(lián)還是繼承。