天天看點

python 繼承

面向對象三大特征-繼承

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()