繼承和多態(tài)

在OOP程序設(shè)計(jì)中,當(dāng)我們定義一個(gè)class的時(shí)候育谬,可以從某個(gè)現(xiàn)有的class繼承券盅,新的class稱為子類(Subclass),而被繼承的class稱為基類斑司、父類或超類(Base class渗饮、Super class)。

比如宿刮,我們已經(jīng)編寫了一個(gè)名為Animal的class互站,有一個(gè)run()方法可以直接打印:

class Animal(object):

? ? ? ? ?def run(self):

? ? ? ? ? ? ? ? ? ? ?print 'Animal is running...'

當(dāng)我們需要編寫Dog和Cat類時(shí)僵缺,就可以直接從Animal類繼承:

class Dog(Animal):

? ? ? ? ?pass

class Cat(Animal):

? ? ? ? ? pass

對(duì)于Dog來(lái)說(shuō)胡桃,Animal就是它的父類,對(duì)于Animal來(lái)說(shuō)磕潮,Dog就是它的子類翠胰。Cat和Dog類似。

繼承有什么好處自脯?最大的好處是子類獲得了父類的全部功能之景。由于Animial實(shí)現(xiàn)了run()方法,因此膏潮,Dog和Cat作為它的子類锻狗,什么事也沒干,就自動(dòng)擁有了run()方法:

dog= Dog()

dog.run()

cat= Cat()

cat.run()

運(yùn)行結(jié)果如下:

Animal is running...

Animal is running...

當(dāng)然焕参,也可以對(duì)子類增加一些方法轻纪,比如Dog類:

class Dog(Animal):

? ? ? ? ?def run(self):

? ? ? ? ? ? ? ? print 'Dog is running...'

? ? ? ? ?def eat(self):

? ? ? ? ? ? ? ? print'Eating meat...'

繼承的第二個(gè)好處需要我們對(duì)代碼做一點(diǎn)改進(jìn)。你看到了叠纷,無(wú)論是Dog還是Cat刻帚,它們r(jià)un()的時(shí)候,顯示的都是Animal is running...涩嚣,符合邏輯的做法是分別顯示Dog is running...和Cat is running...崇众,因此赠摇,對(duì)Dog和Cat類改進(jìn)如下:

classDog(Animal):defrun(self):print'Dog is running...'classCat(Animal):defrun(self):print'Cat is running...'

再次運(yùn)行棚潦,結(jié)果如下:

Dogisrunning...Catisrunning...

當(dāng)子類和父類都存在相同的run()方法時(shí),我們說(shuō),子類的run()覆蓋了父類的run()怨绣,在代碼運(yùn)行的時(shí)候利耍,總是會(huì)調(diào)用子類的run()所森。這樣芥备,我們就獲得了繼承的另一個(gè)好處:多態(tài)。

要理解什么是多態(tài)坤塞,我們首先要對(duì)數(shù)據(jù)類型再作一點(diǎn)說(shuō)明冯勉。當(dāng)我們定義一個(gè)class的時(shí)候,我們實(shí)際上就定義了一種數(shù)據(jù)類型摹芙。我們定義的數(shù)據(jù)類型和Python自帶的數(shù)據(jù)類型灼狰,比如str、list浮禾、dict沒什么兩樣:

a =list()# a是list類型b = Animal()# b是Animal類型c = Dog()# c是Dog類型

判斷一個(gè)變量是否是某個(gè)類型可以用isinstance()判斷:

>>>isinstance(a, list)True>>>isinstance(b, Animal)True>>>isinstance(c, Dog)True

看來(lái)a交胚、b、c確實(shí)對(duì)應(yīng)著list盈电、Animal蝴簇、Dog這3種類型。

但是等等匆帚,試試:

>>>isinstance(c, Animal)True

看來(lái)c不僅僅是Dog熬词,c還是Animal!

不過(guò)仔細(xì)想想吸重,這是有道理的互拾,因?yàn)镈og是從Animal繼承下來(lái)的,當(dāng)我們創(chuàng)建了一個(gè)Dog的實(shí)例c時(shí)嚎幸,我們認(rèn)為c的數(shù)據(jù)類型是Dog沒錯(cuò)颜矿,但c同時(shí)也是Animal也沒錯(cuò),Dog本來(lái)就是Animal的一種嫉晶!

所以骑疆,在繼承關(guān)系中,如果一個(gè)實(shí)例的數(shù)據(jù)類型是某個(gè)子類车遂,那它的數(shù)據(jù)類型也可以被看做是父類封断。但是斯辰,反過(guò)來(lái)就不行:

>>>b = Animal()>>>isinstance(b, Dog)False

Dog可以看成Animal舶担,但Animal不可以看成Dog。

要理解多態(tài)的好處彬呻,我們還需要再編寫一個(gè)函數(shù)衣陶,這個(gè)函數(shù)接受一個(gè)Animal類型的變量:

defrun_twice(animal):animal.run()? ? animal.run()

當(dāng)我們傳入Animal的實(shí)例時(shí)柄瑰,run_twice()就打印出:

>>>run_twice(Animal())Animalisrunning...Animalisrunning...

當(dāng)我們傳入Dog的實(shí)例時(shí),run_twice()就打印出:

>>>run_twice(Dog())Dogisrunning...Dogisrunning...

當(dāng)我們傳入Cat的實(shí)例時(shí)剪况,run_twice()就打印出:

>>>run_twice(Cat())Catisrunning...Catisrunning...

看上去沒啥意思教沾,但是仔細(xì)想想,現(xiàn)在译断,如果我們?cè)俣x一個(gè)Tortoise類型授翻,也從Animal派生:

classTortoise(Animal):defrun(self):print'Tortoise is running slowly...'

當(dāng)我們調(diào)用run_twice()時(shí),傳入Tortoise的實(shí)例:

>>>run_twice(Tortoise())Tortoiseisrunning slowly...Tortoiseisrunning slowly...

你會(huì)發(fā)現(xiàn)孙咪,新增一個(gè)Animal的子類堪唐,不必對(duì)run_twice()做任何修改,實(shí)際上翎蹈,任何依賴Animal作為參數(shù)的函數(shù)或者方法都可以不加修改地正常運(yùn)行淮菠,原因就在于多態(tài)。

多態(tài)的好處就是荤堪,當(dāng)我們需要傳入Dog合陵、Cat、Tortoise……時(shí)澄阳,我們只需要接收Animal類型就可以了拥知,因?yàn)镈og、Cat碎赢、Tortoise……都是Animal類型举庶,然后,按照Animal類型進(jìn)行操作即可揩抡。由于Animal類型有run()方法户侥,因此,傳入的任意類型峦嗤,只要是Animal類或者子類蕊唐,就會(huì)自動(dòng)調(diào)用實(shí)際類型的run()方法,這就是多態(tài)的意思:

對(duì)于一個(gè)變量烁设,我們只需要知道它是Animal類型替梨,無(wú)需確切地知道它的子類型,就可以放心地調(diào)用run()方法装黑,而具體調(diào)用的run()方法是作用在Animal副瀑、Dog、Cat還是Tortoise對(duì)象上恋谭,由運(yùn)行時(shí)該對(duì)象的確切類型決定糠睡,這就是多態(tài)真正的威力:調(diào)用方只管調(diào)用,不管細(xì)節(jié)疚颊,而當(dāng)我們新增一種Animal的子類時(shí)狈孔,只要確保run()方法編寫正確信认,不用管原來(lái)的代碼是如何調(diào)用的。這就是著名的“開閉”原則:

對(duì)擴(kuò)展開放:允許新增Animal子類均抽;

對(duì)修改封閉:不需要修改依賴Animal類型的run_twice()等函數(shù)嫁赏。

繼承還可以一級(jí)一級(jí)地繼承下來(lái),就好比從爺爺?shù)桨职钟突印⒃俚絻鹤舆@樣的關(guān)系潦蝇。而任何類,最終都可以追溯到根類object深寥,這些繼承關(guān)系看上去就像一顆倒著的樹护蝶。比如如下的繼承樹:

小結(jié)

繼承可以把父類的所有功能都直接拿過(guò)來(lái),這樣就不必重零做起翩迈,子類只需要新增自己特有的方法持灰,也可以把父類不適合的方法覆蓋重寫;

有了繼承负饲,才能有多態(tài)堤魁。在調(diào)用類實(shí)例方法的時(shí)候,盡量把變量視作父類類型返十,這樣妥泉,所有子類類型都可以正常被接收;

舊的方式定義Python類允許不從object類繼承洞坑,但這種編程方式已經(jīng)嚴(yán)重不推薦使用盲链。任何時(shí)候,如果沒有合適的類可以繼承迟杂,就繼承自object類刽沾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市排拷,隨后出現(xiàn)的幾起案子侧漓,更是在濱河造成了極大的恐慌,老刑警劉巖监氢,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件布蔗,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡浪腐,警方通過(guò)查閱死者的電腦和手機(jī)纵揍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)议街,“玉大人泽谨,你說(shuō)我怎么就攤上這事。” “怎么了隔盛?”我有些...
    開封第一講書人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)拾稳。 經(jīng)常有香客問(wèn)我吮炕,道長(zhǎng),這世上最難降的妖魔是什么访得? 我笑而不...
    開封第一講書人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任龙亲,我火速辦了婚禮,結(jié)果婚禮上悍抑,老公的妹妹穿的比我還像新娘鳄炉。我一直安慰自己,他們只是感情好搜骡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開白布拂盯。 她就那樣靜靜地躺著,像睡著了一般记靡。 火紅的嫁衣襯著肌膚如雪谈竿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評(píng)論 1 299
  • 那天摸吠,我揣著相機(jī)與錄音空凸,去河邊找鬼。 笑死寸痢,一個(gè)胖子當(dāng)著我的面吹牛呀洲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播啼止,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼道逗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了献烦?” 一聲冷哼從身側(cè)響起憔辫,我...
    開封第一講書人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎仿荆,沒想到半個(gè)月后贰您,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拢操,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年锦亦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片令境。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡杠园,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出舔庶,到底是詐尸還是另有隱情抛蚁,我是刑警寧澤陈醒,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站瞧甩,受9級(jí)特大地震影響钉跷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜肚逸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一爷辙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧朦促,春花似錦膝晾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至禀忆,卻和暖如春歹颓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背油湖。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工巍扛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乏德。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓撤奸,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親喊括。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胧瓜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • date: 2016-10-09 18:45:18 這里繼承和多態(tài)的概念與java的概念差不多。概念還是需要多次理...
    樸有天虹閱讀 267評(píng)論 0 0
  • 繼承和多態(tài): 在OOP程序設(shè)計(jì)中郑什,當(dāng)我們定義一個(gè)class的時(shí)候府喳,可以從某個(gè)現(xiàn)有的class繼承,新的class稱...
    黃大臻Dzreal閱讀 241評(píng)論 0 0
  • 在OPP程序設(shè)計(jì)中蘑拯,當(dāng)我們定義一個(gè)class的時(shí)候钝满,可以從某個(gè)現(xiàn)有的class繼承,新的class稱為子類申窘。而被繼...
    界面大叔閱讀 257評(píng)論 0 0
  • 來(lái)自廖雪峰class(類)可以被繼承弯蚜,新的class稱為子類(Subclass),被繼承的class是基類、父類或...
    Ji_uu閱讀 353評(píng)論 0 0
  • 繼承有什么好處剃法?最大的好處是子類獲得了父類的全部功能碎捺。由于Animial實(shí)現(xiàn)了run()方法,因此,Dog和Cat...
    牛崽兒酷閱讀 382評(píng)論 0 0