1. 程式人生 > 實用技巧 >19.面向物件-繼承與多型

19.面向物件-繼承與多型

面向物件的繼承與多型

1.繼承

繼承 : 一個類除了自身擁有的屬性方法外,還獲取了另一個類的屬性方法
被繼承的是父類(基類,超類)
繼承的是子類(衍生類)    
繼承種類:
    1.單繼承
    2.多繼承
python中所有類的父類是 object
1.1 單繼承
# 單繼承
"""
子類只能繼承父類的公有成員,不能繼承私有成員
在繼承的環境中,物件的調取順序:
    物件中->自己類中->父類中  都沒有報錯
"""
class Human():
    person="遠古人類"
    __mimi="未解之謎"
    def drink(self):
        print("茹毛飲血")
    def __eat(self):
        print("吃的是烤肉")

class Man(Human):#繼承父類
    def siyou(self):
        self.__eat()
    def drink(self):
        print("現代人喝飲料")

obj = Man()
# 1.子類可以使用父類的公有成員
print(obj.person) #遠古人類

# 2.子類不能使用父類的私有成員
"""
obj.siyou() #報錯 : 'Man' object has no attribute '_Man__eat'
"""
# 3.子類可以重寫父類的公有成員
obj.drink() #現代人喝飲料
1.2 多繼承
"""
多繼承的弊端 : 
    會造成菱形繼承這種情況,理不清呼叫順序
super()物件會按照 mro 列表的順序依次呼叫,解決菱形繼承存在的問題
    類名.mro() 返回列表
    1.super 本身是一個類,super()是一個物件,用於掉用父類的繫結方法
	2.super 只應用在繫結方法中,預設自動傳遞self引數(前提: super所在作用域存在self)
	3.super作用 : 用於解決複雜的多繼承呼叫順序
	
經典類: 深度優先(python2.x)
新式類: 廣度優先(python3.x)->橫著遍歷一級父類,二級父類...到最後父類

寫多繼承時,儘量避免造成不同類相同方法名的情況,提高程式碼質量 ,高內聚,低耦合
高內聚: 一個模組只完成一個任務,專一性高
低耦合: 模組與模組之間可以彼此獨立不衝突,方便移植複用
"""

# 1.多繼承
class Father():
    pty="摳腳大叔"
    def hobby(self):
        print("打球")
class Mother():
    pty="貌美如花"
    def hobby(self):
        print("刷韓劇")

class Son(Father,Mother): #繼承父類
    pty="三好學生"
    def hobby(self):
        print("LOL")
    # 1.使用類呼叫類中成員
    def lei(self):
        print(Mother.pty)
        Father.hobby(self) #注意引數別忘寫
    # 2.使用物件呼叫類中成員
    """物件呼叫順序 : 物件成員->自己類成員->父類成員"""
    def duixiang(self):
        print(self.pty)
        self.hobby()
    # 3.使用super呼叫父類中成員
    """繫結方法 : 會自動把作用域self物件當成引數進行傳遞"""
    def sup(self):
        print(super().pty) #多個父類成員一樣,找第一個繼承的父類
        super().hobby() 

obj = Son()
obj.lei() #貌美如花,打球
obj.duixiang() #三好學生 LOL
obj.sup() #摳腳大叔,打球

# 2.菱形繼承(鑽石繼承)
class Human():
    pty=4
    def feel(self):
        print("天熱,脫1")
        print(self.pty)
        print("天冷,穿虎皮2")
class Man(Human):
    pty=3
    def feel(self):
        print("天熱了,光膀子3")
        super().feel()
        print("天冷了,穿羽絨服4")
class Woman(Human):
    pty=2
    def feel(self):
        print("天熱了,脫衣服5")
        super().feel()
        print("天冷了,穿羽絨服6")
class Son(Man,Woman):
    pty=1
    def feel(self):
        print("天熱了,光屁股7")
        super().feel()
        print("天冷了,穿棉襖8")    

obj = Son()
obj.feel() 
"""
天熱了,光屁股7
天熱了,光膀子3
天熱了,脫衣服5
天熱,脫1
1
天冷,穿虎皮2
天冷了,穿羽絨服6
天冷了,穿羽絨服4
天冷了,穿棉襖8
"""
lst=Son.mro() #檢視 super()物件呼叫順序
print(lst)
"""
[
<class '__main__.Son'>,
<class '__main__.Man'>,
 <class '__main__.Woman'>,
 <class '__main__.Human'>,
 <class 'object'>
 ]
"""

# 3.相關函式
# 1.issubclass 判斷誰是否是誰子類
"""
在判斷子父關係時,只要在一條繼承鏈上,就有繼承關係
語法:
    1.issubclass(子類,父類) 滿足返回True
    2.issubclass(子類,(父類1,父類2,....)) 只要滿足一個就返回True
"""
res=issubclass(Son,Man) #True
res=issubclass(Son,Human) #True
print(res)

# 2.isinstance 判斷物件是否是這個類(物件與類之間的關係)
"""
在判斷物件型別時,只要在一條繼承鏈上,就有繼承關係
語法與issubclass一樣
"""
class Car():
    pass
obj = Son()
print(isinstance(obj,Man)) #True
print(isinstance(obj,Human)) #True
print(isinstance(obj,Car)) #False
print(isinstance(obj,(Car,Human)))#True    

2.多型

# 1.多型
"""
多型: 不同的子類物件,呼叫相同的父類方法,產生不同的執行結果
特徵: 繼承,重寫,針對於物件
作用: 在公司中,統一命名規則
"""
class Soldier(): #士兵
    def attack(self): #攻擊  
        pass
    def back(self):  #撤退
        pass

class Army(Soldier): #陸軍
    def attack(self):
        print("包子雷")
    def back(self):
        print("輕功水上漂")
class Navy(Soldier): #海軍
    def attack(self):
        print("魚叉")
    def back(self):
        print("水遁")
class AirForce(Soldier):
    def attack(self):
        print("導彈")
    def back(self):
        print("跳傘,落地成盒")

# 建立陸軍士兵
objArmy=Army()
# 建立海軍士兵
objNavy=Navy()
# 建立空軍士兵
objAirForce=AirForce()

# 整裝待發
lst=[objArmy,objNavy,objAirForce]
strvar="""
1.全軍出擊
2.全體撤退
3.陸軍掩護其他兵種撤退
各就各位,將軍請下令:
"""
num=input(strvar)
for i in lst:
    if num=="1":
        i.attack()
    elif num=="2":
        i.back()
    elif num=="3":
        if isinstance(i,Army):
            i.attack()
        else:
            i.back()
    else:
        print("聽不清~~")
        break