9.5. 繼承
成都網(wǎng)絡(luò)公司-成都網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)建站10多年經(jīng)驗(yàn)成就非凡,專(zhuān)業(yè)從事網(wǎng)站建設(shè)、做網(wǎng)站,成都網(wǎng)頁(yè)設(shè)計(jì),成都網(wǎng)頁(yè)制作,軟文平臺(tái),一元廣告等。10多年來(lái)已成功提供全面的成都網(wǎng)站建設(shè)方案,打造行業(yè)特色的成都網(wǎng)站建設(shè)案例,建站熱線(xiàn):028-86922220,我們期待您的來(lái)電!
當(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)部方法。
@[toc]
全局只有一個(gè)實(shí)例
font color=#03a3e3 該實(shí)現(xiàn)方式在多線(xiàn)程場(chǎng)景下不安全
繼承其他類(lèi)的類(lèi)稱(chēng)為派生類(lèi)(derived class)
被其他類(lèi)繼承的類(lèi)稱(chēng)為這些類(lèi)的基類(lèi)(base
class)
需要注意圓括號(hào)中基類(lèi)的順序:font color=#03a3e3 從左到右搜索 font
多繼承會(huì)導(dǎo)致菱形 diamond關(guān)系:有至少一個(gè)基類(lèi)可以從子類(lèi)經(jīng)由多個(gè)繼承路徑到達(dá)
基類(lèi)方法可能被多次調(diào)用
防止重復(fù)訪(fǎng)問(wèn),每個(gè)基類(lèi)只調(diào)用一次
通過(guò)子類(lèi)實(shí)例對(duì)象課調(diào)用父類(lèi)已被覆蓋
慎用多繼承(二義性)
– 對(duì)已有的運(yùn)算符重新進(jìn)行定義,賦予其另一種功能,以適應(yīng)不同的數(shù)據(jù)類(lèi)型
– 運(yùn)算符重載不能改變其本來(lái)寓意
– 運(yùn)算符重載只是一種 “語(yǔ)法上的方便” (sugar)
– 是一種函數(shù)調(diào)用的方式