9.5. 繼承
讓客戶(hù)滿(mǎn)意是我們工作的目標(biāo),不斷超越客戶(hù)的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶(hù),將通過(guò)不懈努力成為客戶(hù)在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊(cè)、網(wǎng)頁(yè)空間、營(yíng)銷(xiāo)軟件、網(wǎng)站建設(shè)、蒲縣網(wǎng)站維護(hù)、網(wǎng)站推廣。
當(dāng)然,如果一種語(yǔ)言不支持繼承就,“類(lèi)”就沒(méi)有什么意義。派生類(lèi)的定義如下所示:
class DerivedClassName(BaseClassName):
命名 BaseClassName (示例中的基類(lèi)名)必須與派生類(lèi)定義在一個(gè)作用域內(nèi)。除了類(lèi),還可以用表達(dá)式,基類(lèi)定義在另一個(gè)模塊中時(shí)這一點(diǎn)非常有用:
class DerivedClassName(modname.BaseClassName):
派生類(lèi)定義的執(zhí)行過(guò)程和基類(lèi)是一樣的。構(gòu)造派生類(lèi)對(duì)象時(shí),就記住了基類(lèi)。這在解析屬性引用的時(shí)候尤其有用:如果在類(lèi)中找不到請(qǐng)求調(diào)用的屬性,就搜索基類(lèi)。如果基類(lèi)是由別的類(lèi)派生而來(lái),這個(gè)規(guī)則會(huì)遞歸的應(yīng)用上去。
派生類(lèi)的實(shí)例化沒(méi)有什么特殊之處: DerivedClassName() (示列中的派生類(lèi))創(chuàng)建一個(gè)新的類(lèi)實(shí)例。方法引用按如下規(guī)則解析:搜索對(duì)應(yīng)的類(lèi)屬性,必要時(shí)沿基類(lèi)鏈逐級(jí)搜索,如果找到了函數(shù)對(duì)象這個(gè)方法引用就是合法的。
派生類(lèi)可能會(huì)覆蓋其基類(lèi)的方法。因?yàn)榉椒ㄕ{(diào)用同一個(gè)對(duì)象中的其它方法時(shí)沒(méi)有特權(quán),基類(lèi)的方法調(diào)用同一個(gè)基類(lèi)的方法時(shí),可能實(shí)際上最終調(diào)用了派生類(lèi)中的覆蓋方法。(對(duì)于 C++ 程序員來(lái)說(shuō),Python 中的所有方法本質(zhì)上都是 虛 方法。)
派生類(lèi)中的覆蓋方法可能是想要擴(kuò)充而不是簡(jiǎn)單的替代基類(lèi)中的重名方法。有一個(gè)簡(jiǎn)單的方法可以直接調(diào)用基類(lèi)方法,只要調(diào)用: BaseClassName.methodname(self, arguments)。有時(shí)這對(duì)于客戶(hù)也很有用。(要注意只有 BaseClassName 在同一全局作用域定義或?qū)霑r(shí)才能這樣用。)
Python 有兩個(gè)用于繼承的函數(shù):
函數(shù) isinstance() 用于檢查實(shí)例類(lèi)型: isinstance(obj, int) 只有在 obj.__class__ 是 int 或其它從 int 繼承的類(lèi)型
函數(shù) issubclass() 用于檢查類(lèi)繼承: issubclass(bool, int) 為 True,因?yàn)?bool 是 int 的子類(lèi)。
然而, issubclass(float, int) 為 False,因?yàn)?float 不是 int 的子類(lèi)。
類(lèi)(Class): 用來(lái)描述具有相同的屬性和方法的對(duì)象的集合。
類(lèi)變量:類(lèi)變量在整個(gè)實(shí)例化的對(duì)象中是公用的。類(lèi)變量定義在類(lèi)中且在函數(shù)體之外。類(lèi)變量通常不作為實(shí)例變量使用。
類(lèi)有一個(gè)名為 __init__() 的特殊方法(構(gòu)造方法),該方法在類(lèi)實(shí)例化時(shí)會(huì)自動(dòng)調(diào)用
self:self 代表的是類(lèi)的實(shí)例,代表當(dāng)前對(duì)象的地址,而 self.class 則指向類(lèi)。
類(lèi)調(diào)用 Car.weight
實(shí)例化 car01=Car(5)
實(shí)例對(duì)象調(diào)用 car01.weght
我們?cè)跇?gòu)造類(lèi)時(shí),Python3默認(rèn)我們繼承了object這個(gè)基類(lèi),我個(gè)人理解object就是個(gè)空的類(lèi),可以不用管為何要在括號(hào)中寫(xiě)上object,這是Python3的特性,在python2中如果你沒(méi)有寫(xiě)object的話(huà)不會(huì)默認(rèn)繼承了object這個(gè)基類(lèi)。
同樣的我們自己希望繼承的父類(lèi)只需要把objetc改為我們自己定義的類(lèi)名即可。子類(lèi)中可以擁有父類(lèi)中所有的公有屬性和方法,但是可以通過(guò)在變量名前加下劃線(xiàn)使其變?yōu)樗接?,這樣子類(lèi)就不可以訪(fǎng)問(wèn)父類(lèi)中的成員了。
以下三個(gè)公交車(chē)類(lèi)的父類(lèi)均為客車(chē)類(lèi),我們可以寫(xiě)一個(gè)funcs方法使得每次調(diào)用funcs方法時(shí),傳入不同的對(duì)象以執(zhí)行不同的func方法,具體實(shí)現(xiàn)如下:
主函數(shù) :
可以看到,我將小 汽車(chē) 實(shí)例化為帶有重量為5t的一個(gè)具體對(duì)象,將客車(chē)實(shí)例化為帶有重量為20t的一個(gè)具體對(duì)象,將三個(gè)公交車(chē)實(shí)例化為帶有重量為15t的一個(gè)具體對(duì)象.
如上圖所示,我每次在調(diào)用funcs方法時(shí)都傳入了一個(gè)實(shí)例化對(duì)象,funcs根據(jù)不同的對(duì)象執(zhí)行相應(yīng)的內(nèi)部方法。
繼承是子類(lèi)復(fù)用父類(lèi)的屬性和方法的機(jī)制,類(lèi)的繼承是以生活中繼承為靈感設(shè)計(jì)的。
生活中繼承的例子有很多,例如,汽車(chē)的發(fā)展歷程就體現(xiàn)了繼承。最早汽車(chē)的輪胎都是實(shí)心的,功能少,性能差,而如今汽車(chē)的功能越來(lái)越多,性能越來(lái)越好,這是經(jīng)過(guò)一代一代的發(fā)展而來(lái)的,每一代比上一代擴(kuò)充了一些功能,改進(jìn)了一些性能??v觀整個(gè)汽車(chē)的發(fā)展史,每一代汽車(chē)都是在上一代汽車(chē)的特征和行為的基礎(chǔ)之上,進(jìn)行了設(shè)計(jì)和改良。這其中有些功能沒(méi)有改變,有些功能是新增的,也有些功能經(jīng)過(guò)了改良。例如,從第一代的汽車(chē)到現(xiàn)在的汽車(chē),做交通工具這一特點(diǎn)始終都在沿用。
生活中汽車(chē)的例子,與計(jì)算機(jī)中的繼承是非常相似的。這么一代又一代的更新是有好處的。
首先,節(jié)省了設(shè)計(jì)流程,不用閉門(mén)造車(chē)。
其次,在前一代汽車(chē)基礎(chǔ)之上設(shè)計(jì),這樣原來(lái)重復(fù)的生產(chǎn)技術(shù)還可以復(fù)用,再設(shè)計(jì)一些新增的功能,這樣就能大大地提高生產(chǎn)效率。
下面介紹一個(gè)實(shí)際案例,來(lái)說(shuō)明繼承的用處。
假設(shè)設(shè)計(jì)一個(gè)師生管理系統(tǒng),具有學(xué)生和教師兩種用戶(hù),需要設(shè)計(jì)兩個(gè)類(lèi),一個(gè)學(xué)生類(lèi)(Student),一個(gè)教師類(lèi)(Teacher)。Student類(lèi)有學(xué)號(hào)、姓名、性別、年齡、用戶(hù)名、密碼等屬性,Teacher類(lèi)有姓名、性別、年齡、用戶(hù)名、密碼、學(xué)歷等屬性,這兩個(gè)類(lèi)中都有屬性的getter和setter方法。由此可知,這兩個(gè)類(lèi)中有許多相同的屬性和方法,也就是說(shuō)代碼有冗余。為了避免這樣的情況,就可以使用繼承來(lái)優(yōu)化設(shè)計(jì)。將Student類(lèi)和Teacher類(lèi)中相同的屬性和方法抽取出來(lái),單獨(dú)作為一個(gè)父類(lèi),這個(gè)父類(lèi)稱(chēng)為用戶(hù)類(lèi)(User),而Student類(lèi)和Teacher類(lèi)作為子類(lèi)繼承父類(lèi)User。Student類(lèi)和Teacher類(lèi)中就只放自己特有的屬性和方法即可。由于這兩個(gè)類(lèi)都繼承User類(lèi),因此User類(lèi)中的屬性和方法,它們可以直接使用。需要指出的是,在繼承中私有屬性和私有方法是不能被繼承的。
繼承提高了代碼的重用性,減少了代碼和數(shù)據(jù)的冗余度。另外,如果要修改用戶(hù)名屬性,不采用繼承的情況下,兩個(gè)類(lèi)的屬性都需要修改,而使用繼承后,只需要修改父類(lèi)的用戶(hù)名屬性即可。由此可知,繼承使代碼的修改更加方便。
關(guān)于Python的基礎(chǔ)問(wèn)題可以看下這個(gè)網(wǎng)頁(yè)的視頻教程,網(wǎng)頁(yè)鏈接,希望我的回答能幫到你。