在OPP程序設(shè)計(jì)中,當(dāng)我們定義一個(gè)class的時(shí)候,可以從某個(gè)現(xiàn)有的class繼承,新的class稱為子類。而被繼承的class稱為基類或父類。
比如,我們已經(jīng)編寫了一個(gè)名為Animal的class,有一個(gè)run()方法可以直接接打?。?/p>
class Animals:
??? def run(self):
??? print('Animals is running...')
當(dāng)我們需要編寫Dog和Cat類時(shí),可以直接從Animals中繼承:
class Dog(Animals):
??? pass
class Cat(Animals):
??? pass
dog = Dog()
dog.run()
cat = Cat()
在這里Animals時(shí)父類,Cat和Dog就是子類,子類能獲取父類的功能。
運(yùn)行的結(jié)果是:
Animals is running...
Animals is running...
當(dāng)子類和父類都存在相同的方法是時(shí),子類會(huì)覆蓋父類,這樣代碼在運(yùn)行的時(shí)候,就會(huì)調(diào)用子類,這樣我們就獲得了繼承 的另一個(gè)好處:多態(tài)
類是創(chuàng)建實(shí)例的模板,而實(shí)例是一個(gè)一個(gè)具體的對象。各個(gè)實(shí)例擁有的數(shù)據(jù)互相獨(dú)立,互相不影響
方法就是與實(shí)例綁定的函數(shù),和普通函數(shù)不同,方法可以直接訪問實(shí)例的數(shù)據(jù)
使用isinstance():
獲取對象繼承關(guān)系
使用dir();
獲得一個(gè)對象的所有屬性和方法
在編寫程序的時(shí)候,千萬不要把實(shí)例屬性和類屬性使用相同的名字,因?yàn)橄嗤Q的實(shí)例屬性會(huì)屏蔽類屬性,但當(dāng)你刪除實(shí)例屬性后,在使用相同的名稱,返回的將會(huì)是類屬性
多態(tài):

繼承還可以一級一級地繼承下來,就好比從爺爺?shù)桨职?、再到兒子這樣的關(guān)系。而任何類,最終都可以追溯到根類object,這些繼承關(guān)系看上去就像一顆倒著的樹
繼承可以把父類的所有功能都直接拿過來,這樣就不必重零做起,子類只需要新增自己特有的方法,也可以把父類不適合的方法覆蓋重寫。
動(dòng)態(tài)語言的鴨子類型特點(diǎn)決定了繼承不像靜態(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)
對于一個(gè)變量,我們只需要知道它是Animal類型,無需確切地知道它的子類型,就可以放心地調(diào)用run()方法,而具體調(diào)用的run()方法是作用在Animal、Dog、Cat還是Tortoise對象上,由運(yùn)行時(shí)該對象的確切類型決定,這就是多態(tài)真正的威力:調(diào)用方只管調(diào)用,不管細(xì)節(jié),而當(dāng)我們新增一種Animal的子類時(shí),只要確保run()方法編寫正確,不用管原來的代碼是如何調(diào)用的。這就是著名的“開閉”原則: