python類繼承的重寫和super


給已經存在的類添加新的行為,繼承是非常好的實現方式。但是如果要改變行為呢?比如在Python繼承擴展內置類,我們的contact類只允許一個名字和一個郵箱,但是如果要對某些人增加電話號碼呢?這里可以通過非常簡單的給他增加一個電話號碼的屬性來實現,但是如果想這第3個變量在初始化類的時候就可用,就需要重寫__init__函數

重寫就是在子類里用一個(和超類相同的名字)新的方法來改變或者覆蓋超類里的這個方法。做這個不需要特殊的語法,會自動執行子類新創建的方法而不是超類的方法。以下是在之前Contact類中,使用Friend子類來繼承

class ContactList(list):
    def search(self, name):
        '''Return all contacts that contain the search value
           in their name.'''
        matching_contacts = []
        for contact in self:
            if name in contact.name:
                matching_contacts.append(contact)
        return matching_contacts

class Contact:
    all_contacts = ContactList()
  
    def __init__(self, name, email):
        self.name = name
        self.email = email
        Contact.all_contacts.append(self)


class Supplier(Contact):
    def order(self, order):
        print("If this were a real system we would send"
                 "{} order to {}".format(order, self.name))


class Friend(Contact):
    '''以下是重寫方法,注意這個方法沒有將name和email等加入父類的all_contact   '''
    def __init__(self, name, email, phone):
        self.name = name 
        self.email = email
        self.phone = phone

class Friend1(Contact):
    '''通過super得到父類對象的實例,並且調用這個對象的__init__方法,
       傳遞給它預期的參數,然后這個類做了自己的初始化,即設置phone屬性'''
    def __init__(self, name, email, phone):
        super().__init__(name, email)
        self.phone = phone

不只有__init__,任何方法都可以被重寫。在這個例子中,Contact和Friend類有重復的代碼來創建name和email,這會導致維護變得復雜。需要警惕的是,Friend類忽略了把自己加到all_contacts列表里,這個列表是我們在Contact類里創建的。將以上代碼保存為order.py腳本,如下是在交互的解釋器里運行的結果如下:

$ python -i order.py 
>>> c1 = Contact("John A", "johna@example.com")
>>> c2 = Contact("John B", "johnb@example.com")
>>> c3 = Contact("Jenna C", "jennac@example.com")
>>> c4 = Friend("Friend c", "Friendc@example.com",'0592-5566778')
>>> c5 = Friend("Friend 5", "Friend5@example.com",'0592-1122334')
>>> c6 = Friend1("Friend 6", "Friend6@example.com",'0592-4455667')
>>> c7 = Friend1("Friend 7", "Friend7@example.com",'0592-7788990')
>>> [c.name for c in Contact.all_contacts]
['John A', 'John B', 'Jenna C', 'Friend 6', 'Friend 7']

我們真正需要的是一種可以調用父類的代碼的方法,這個就是super函數的功能,他返回一個父類的實例化對象,允許我們直接調用父類的方法,如上例中的Friend1類。

super()可以在任何方法中調用,不只是__init__方法,這就意味着通過重寫和調用super,可以修改所有的方法。可以在方法的任何位置用super。

 

參考:

1、《Python3 面向對象編程》 [加]Dusty Philips 著


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM