強制子類重寫父類中的方法

Python v3.7.0

方案一(推薦):定義抽象基類,只要把一個方法定義成抽象方法,那解釋器就會要求子類必須重寫這個方法,要注意的是,如果抽象方法沒有被重寫,那麼子類在實例化時,就會拋出TypeError異常,而不需要等到調用函數。

import abc

class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def speak(self):
        pass

class Dog(Animal):
    def run(self):
        pass

if __name__ == '__main__':
    dog = Dog()

運行以上代碼,會拋出異常:

TypeError: Can't instantiate abstract class Dog with abstract methods speak

只有在Dog子類中,重寫speak方法,纔可以正常實例化子類。

方案二:指定父類方法拋出NotImplementedError異常

class Animal1():
    def speak(self):
        raise NotImplementedError

class Dog1(Animal1):
    def run(self):
        pass

if __name__ == '__main__':
    dog = Dog1()
    dog.speak()

子類中若沒有重寫speak方法,也可以正常實例化,但是調用此方法時,就會拋出NotImplementedError異常;


補充:

  1. 在父類中定義的私有方法,其作用範圍僅在當前類,若在子類中重寫,實際上並不會起效果,原因:以雙下劃線前綴開頭的屬性或方法,Python解釋器會重寫其名稱,以便在類被擴展的時候不容易產生衝突,這被稱之爲名稱修飾(name mangling),如下所示:
class Test:
    def __init__(self):
        self.__foo = True

    def __bar(self):
        return "bar"

t = Test()
print(dir(t))
print(t._Test__foo)
print(t._Test__bar())

輸出內容如下,注意列表前兩個值,這同時也說明在Python中是沒有絕對私有的變量或方法的。

['_Test__bar', '_Test__foo', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
True
bar
  1. 在類的繼承中,如果在子類中重寫了父類方法,但有時也希望能同時實現父類的功能,最常見的場景之一就是父類構造方法中的初始值無法被繼承,可以在子類中使用super 函數來調用父類中的方法,特別是多重繼承的情況;如下面的例子:
class Animal:
    def __init__(self):
        self.hungry = True

    def eat(self):
        if self.hungry:
            print('No!')
        else:
            print('Yes!')


class Bird(Animal):
    def __init__(self):
        self.song = '~~~'

    def sing(self):
        print(self.song)

bird = Bird()
bird.sing()   # 正常
bird.eat()    # 拋出異常:AttributeError: 'Bird' object has no attribute 'hungry'

解決的方法是在子類的構造函數中,使用super方法調用父類的構造函數,如下:

class Bird(Animal):
    def __init__(self):
        super().__init__()
        self.song = '~~~'

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章