在OPP程序設計中辛馆,當我們定義一個class的時候,可以從某個現(xiàn)有的class繼承昙篙,新的class稱為子類苔可。而被繼承的class稱為基類或父類。
比如映屋,我們已經(jīng)編寫了一個名為Animal的class同蜻,有一個run()方法可以直接接打印:
class Animals:
??? def run(self):
??? print('Animals is running...')
當我們需要編寫Dog和Cat類時湾蔓,可以直接從Animals中繼承:
class Dog(Animals):
??? pass
class Cat(Animals):
??? pass
dog = Dog()
dog.run()
cat = Cat()
在這里Animals時父類默责,Cat和Dog就是子類,子類能獲取父類的功能杖虾。
運行的結(jié)果是:
Animals is running...
Animals is running...
當子類和父類都存在相同的方法是時媒熊,子類會覆蓋父類坟比,這樣代碼在運行的時候滤愕,就會調(diào)用子類,這樣我們就獲得了繼承 的另一個好處:多態(tài)
類是創(chuàng)建實例的模板注竿,而實例是一個一個具體的對象魂贬。各個實例擁有的數(shù)據(jù)互相獨立,互相不影響
方法就是與實例綁定的函數(shù)宣谈,和普通函數(shù)不同键科,方法可以直接訪問實例的數(shù)據(jù)
使用isinstance():
獲取對象繼承關系
使用dir();
獲得一個對象的所有屬性和方法
在編寫程序的時候勋颖,千萬不要把實例屬性和類屬性使用相同的名字,因為相同名稱的實例屬性會屏蔽類屬性侥祭,但當你刪除實例屬性后茄厘,在使用相同的名稱,返回的將會是類屬性
多態(tài):
繼承還可以一級一級地繼承下來胎署,就好比從爺爺?shù)桨职忠ぶ汀⒃俚絻鹤舆@樣的關系。而任何類,最終都可以追溯到根類object聊训,這些繼承關系看上去就像一顆倒著的樹
繼承可以把父類的所有功能都直接拿過來恢氯,這樣就不必重零做起鼓寺,子類只需要新增自己特有的方法勋磕,也可以把父類不適合的方法覆蓋重寫挂滓。
動態(tài)語言的鴨子類型特點決定了繼承不像靜態(tài)語言那樣是必須的。
案例:
classAnimal(object):
defrun(self):
print('Animal is running...')
classDog(Animal):
defrun(self):
print('Dog is running...')
classCat(Animal):
defrun(self):
print('Cat is running...')
defrun_twice(animal):
animal.run()
animal.run()
a=Animal()
d=Dog()
c=Cat()
print('a is Animal?',isinstance(a, Animal))
print('a is Dog?',isinstance(a, Dog))
print('a is Cat?',isinstance(a, Cat))
print('d is Animal?',isinstance(d, Animal))
print('d is Dog?',isinstance(d, Dog))
print('d is Cat?',isinstance(d, Cat))
run_twice(c)
對于一個變量幔虏,我們只需要知道它是Animal類型贝椿,無需確切地知道它的子類型,就可以放心地調(diào)用run()方法瑟蜈,而具體調(diào)用的run()方法是作用在Animal渣窜、Dog、Cat還是Tortoise對象上夷都,由運行時該對象的確切類型決定予颤,這就是多態(tài)真正的威力:調(diào)用方只管調(diào)用,不管細節(jié)党饮,而當我們新增一種Animal的子類時驳庭,只要確保run()方法編寫正確,不用管原來的代碼是如何調(diào)用的蹲堂。這就是著名的“開閉”原則: