面向對象三大特征-繼承
2、繼承
1、繼承簡單介紹
# 繼承
# 定義一個類 Animal(動物)
# 這個類中需要兩個方法:run() sleep()
class Animal:
def run(self):
print('動物會跑~~~')
def sleep(self):
print('動物睡覺~~~')
# def bark(self):
# print('動物嚎叫~~~')
# 定義一個類 Dog(狗)
# 這個類中需要三個方法:run() sleep() bark()
# class Dog:
# def run(self):
# print('狗會跑~~~')
# def sleep(self):
# print('狗睡覺~~~')
# def bark(self):
# print('汪汪汪~~~')
# 有一個類,能夠實作我們需要的大部分功能,但是不能實作全部功能
# 如何能讓這個類來實作全部的功能呢?
# ① 直接修改這個類,在這個類中添加我們需要的功能
# - 修改起來會比較麻煩,并且會違反OCP原則
# ② 直接建立一個新的類
# - 建立一個新的類比較麻煩,并且需要大量的進行複制粘貼,會出現大量的重複性代碼
# ③ 直接從Animal類中來繼承它的屬性和方法
# - 繼承是面向對象三大特性之一
# - 通過繼承我們可以使一個類擷取到其他類中的屬性和方法
# - 在定義類時,可以在類名後的括号中指定目前類的父類(超類、基類、super)
# 子類(衍生類)可以直接繼承父類中的所有的屬性和方法
#
# 通過繼承可以直接讓子類擷取到父類的方法或屬性,避免編寫重複性的代碼,并且也符合OCP原則
# 是以我們經常需要通過繼承來對一個類進行擴充
class Dog(Animal):
def bark(self):
print('汪汪汪~~~')
def run(self):
print('狗跑~~~~')
class Hashiqi(Dog):
def fan_sha(self):
print('我是一隻傻傻的哈士奇')
d = Dog()
h = Hashiqi()
# d.run()
# d.sleep()
# d.bark()
# r = isinstance(d , Dog)
# r = isinstance(d , Animal)
# print(r)
# 在建立類時,如果省略了父類,則預設父類為object
# object是所有類的父類,所有類都繼承自object
class Person(object):
pass
# issubclass() 檢查一個類是否是另一個類的子類
# print(issubclass(Animal , Dog))
# print(issubclass(Animal , object))
# print(issubclass(Person , object))
# isinstance()用來檢查一個對象是否是一個類的執行個體
# 如果這個類是這個對象的父類,也會傳回True
# 所有的對象都是object的執行個體
print(isinstance(print , object))
2、方法的重寫
# 繼承
# 定義一個類 Animal(動物)
# 這個類中需要兩個方法:run() sleep()
class Animal:
def run(self):
print('動物會跑~~~')
def sleep(self):
print('動物睡覺~~~')
class Dog(Animal):
def bark(self):
print('汪汪汪~~~')
def run(self):
print('狗跑~~~~')
# 如果在子類中如果有和父類同名的方法,則通過子類執行個體去調用方法時,
# 會調用子類的方法而不是父類的方法,這個特點我們成為叫做方法的重寫(覆寫,override)
# 建立Dog類的執行個體
# d = Dog()
# d.run()
# 當我們調用一個對象的方法時,
# 會優先去目前對象中尋找是否具有該方法,如果有則直接調用
# 如果沒有,則去目前對象的父類中尋找,如果父類中有則直接調用父類中的方法,
# 如果沒有,則去父類的父類中尋找,以此類推,直到找到object,如果依然沒有找到,則報錯
class A(object):
def test(self):
print('AAA')
class B(A):
def test(self):
print('BBB')
class C(B):
def test(self):
print('CCC')
# 建立一個c的執行個體
c = C()
c.test()
3、super()
class Animal:
def __init__(self,name):
self._name = name
def run(self):
print('動物會跑~~~')
def sleep(self):
print('動物睡覺~~~')
@property
def name(self):
return self._name
@name.setter
def name(self,name):
self._name = name
# 父類中的所有方法都會被子類繼承,包括特殊方法,也可以重寫特殊方法
class Dog(Animal):
def __init__(self,name,age):
# 希望可以直接調用父類的__init__來初始化父類中定義的屬性
# super() 可以用來擷取目前類的父類,
# 并且通過super()傳回對象調用父類方法時,不需要傳遞self
super().__init__(name)
self._age = age
def bark(self):
print('汪汪汪~~~')
def run(self):
print('狗跑~~~~')
@property
def age(self):
return self._age
@age.setter
def age(self,age):
self._age = name
d = Dog('旺财',18)
print(d.name)
print(d.age)
4、多重繼承
class A(object):
def test(self):
print('AAA')
class B(object):
def test(self):
print('B中的test()方法~~')
def test2(self):
print('BBB')
# 在Python中是支援多重繼承的,也就是我們可以為一個類同時指定多個父類
# 可以在類名的()後邊添加多個類,來實作多重繼承
# 多重繼承,會使子類同時擁有多個父類,并且會擷取到所有父類中的方法
# 在開發中沒有特殊的情況,應該盡量避免使用多重繼承,因為多重繼承會讓我們的代碼過于複雜
# 如果多個父類中有同名的方法,則會現在第一個父類中尋找,然後找第二個,然後找第三個。。。
# 前邊父類的方法會覆寫後邊父類的方法
class C(A,B):
pass
# 類名.__bases__ 這個屬性可以用來擷取目前類的所有父類
# print(C.__bases__) (<class '__main__.B'>,)
# print(B.__bases__) (<class 'object'>,)
# print(C.__bases__) # (<class '__main__.A'>, <class '__main__.B'>)
c = C()
c.test()