繼承與多型

      在〈繼承與多型〉中尚無留言

繼承(Inherit)

物件導向理論中, 最有用的就是繼承的機制. 比如要設計Pikachu, Eve, Frog三個神奇寶貝. 最快速的方法就是把這三個種類相同處, 設定在父類別Pokemon中, 然後此三種再繼承Pokemon. 此時我們稱Pokemon為父類別, 而Pikachu, Eva, Frog則稱為子類別. 子類別繼承父類別後, 就擁有父類別所有的物件方法, 如setLevel(), getLevel(), 所以子類別就不需要再重新寫一次

class Pokemon(object):
    def __init__(self, level):
        self.level=level
    def setSpeed(self, s):
        self.speed=s
class Pikachu(Pokemon):
    pass
class Eve(Pokemon):
    pass
p1=Pikachu(10)
p1.setSpeed(100)
print(f'p1 level: {p1.level}')
print(f'p1 speed : {p1.speed}')
結果
p1 level: 10
p1 speed : 100

物件變數繼承

物件變數必需觸發物件方法或建構子才會生成,所以物件變數沒有繼不繼承的問題。

子類別方法擴充

 子類別也可以自行擴充其功能

class Pikachu(Pokemon):
    def lighting(self):
        print("一萬伏閃電攻擊")

方法覆蓋(Override)

子類別定義方法時,若名稱與父類別相同,則稱為覆蓋。父類別方法被子類別覆蓋後就屍骨無存。此時若在子類別方法中要調用父類別方法,那該怎麼辦呢? 只此時只好使用觀落音法了,super() 就是廟裏負責觀落音的廟公廟婆,如下代碼中,使用super().getLevel()

在super的參數中, Python 3.0直接空白即可, 若是Python2.0, 則需寫為
super(Pikachu, self).setLevel(level);

其實super()裏的參數, 是為了多重繼承時的設定. 到目前為止, 我們都只講到單一繼承

class Pikachu(Pokemon):
     def lighting(self):
         print("一萬伏閃電攻擊")
     def getLevel(self):
         print("皮卡丘 Level %d" % super().getLevel())

建構子覆蓋

子類別繼承了父類別後,若子類別沒有建構子,則會繼承父類別建構子。但子類別若有建構子,則會覆蓋父類別建構子。

依物件導向理論,Java及C#都會自動加預設建構子,並且於建構子第一行自動加入super()。 但在Python中,並不會自動加super()。所以建議在Python中,每個類別都要寫建構子,並且於子類別建構子的第一行手動加入 super().__init__(),這樣才能調用父類別建構子。

class Pokemon(object):
    def __init__(self, level=0, w=0):
        self.level=level
        print("Pokemon 出生了 : %d" % self.level)
class Pikachu(Pokemon):
    def __init__(self, level=0):
        super().__init__(level)
        print("Pikachu 出生了")
p1=Pikachu(20)
結果 : 
Pokemon 出生了 : 20
Pikachu 出生了

多型(Polymorphism)

在上面的例子中, p1到底是Pokemon, 還是Pikachu, 此時我們也混亂了. 所以有一個函數可以解析此變數的型態, 就是isinstance().

if isinstance(p1, Pokemon):
    print("Pokemon")
else:
    print("Pikachu")

接下來, 再試試下面的代碼

p2=Pikachu()
if isinstance(p2, Pokemon):
    print("p2 是 神奇寶貝")
if isinstance(p2, Pikachu):
    print("p2 是 皮卡丘")
結果 :
p2 是 神奇寶貝
p2 是 皮卡丘

妖壽喔, 怎麼p2是神奇寶貝, 也是皮卡丘呢. 這個叫廢話, 皮卡丘就是神奇寶貝啊, 這就是多型的意思. 不過, 神奇寶貝不一定是皮卡丘喔.

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *