python物件導向(二)繼承:最直接的程式碼複用

小丑与锁鸟發表於2024-04-07

繼承簡介
繼承是指透過在建立類時提供另一個類(稱為父類)的名稱,來獲取父類的屬性與方法。繼承最明顯的作用就是節約程式碼量,不需要重複定義已經存在的屬性與方法。但是深入思考就會發現,複用只是繼承的附帶作用,繼承最有意義的一點,是將不同的類聯絡了起來,讓不同的類之間能夠有一定的共性。當我們在面對不同類的時候,如果能按照他們的共性按圖索驥,那麼會輕鬆不少。例如,如果我們已經考取了c1駕照,當我們看到半掛卡車的時候,即使沒有開過,也可以立即理解其操作方式,從而節省了學習時間。
私有與重寫
在python中,繼承的內容可以是屬性也可以是方法。有時候我們不想讓一個類的某些屬性或者方法暴露在外(即透過【物件名.屬性】或者【物件名.方法名()】的方式檢視或呼叫),或者不希望被子類繼承,則可以用私有或者重寫的方式來在某種程度上達到我們的目標。私有屬性在命名時以兩個下劃線開頭,私有屬性或方法不可以在直接訪問(也不可以在子類中直接訪問),而是必須要採用一些被額外定義的公共方法訪問。舉個例子:

點選檢視程式碼
class Student(object):
    def __init__(self):
        self.sid = ''
        self.gender = ''
        self.__university = '清華大學'   
class HighSchoolStudent(Student):
    pass
上文的例子中,學生類有一個屬性sid,子類HighSchoolStudent繼承了這個屬性(高中生也會有學號)。然而,並不適合所有學生都上過大學,高中生類顯然沒有從學生類中繼承到university屬性。如果我們試圖獲取這個屬性,結果會是AttributeError: 'HighSchoolStudent' object has no attribute '__university'的屬性錯誤。 現在讓我們為學生類新增一個方法,來檢視學生的目標大學。
點選檢視程式碼
class Student(object):
    def __init__(self):
        self.sid = ''
        self.gender = ''
        self.__university = '清華大學'
    def TargetSchool(self):
        print(f'我將努力學習,爭取{self.__university}的offer!')
class HighSchoolStudent(Student):
    pass
此時,繼承了HighSchoolStudent方法的高中生,即使不能直接檢視有__university屬性,也可以用繼承來的方法TargetSchool來檢視目標學校。 然而,不是所有人都把目標定為清華大學,此時我們就需要在例項中修改屬性和方法。不管是屬性還是方法,如果在子類中重新定義了同名內容,那麼最終使用的是子類中定義的方法,這叫做重寫。我們可以透過重寫TargetSchool來改變目標學校,這裡就不再演示。然而要注意的是,我們重寫的方法,是無法透過正常的屬性訪問方式來獲取__university屬性的,因為它被私有了。訪問這類私有屬性通常也是不合適的,如果真的需要,可以用self._定義類名(在這裡是_Student)__university 的方式強制訪問。 到這裡,繼承的作用已經較為清晰,我們可以對子類物件直接使用父類方法而不需要重新定義,我們也可以重寫父類方法來獲得不同於父類的行為或屬性。還有一點不完美:一名高中生除了是學生,可能還是某個獨立遊戲的開發者。如果我們有如下定義:
點選檢視程式碼
class Programmer(object):
    def __init__(self):
        self.gender = 'male'
        language = 'Python'
    def coding(self):
        print(f'寫{self.language}程式碼')
那麼如何利用這個類讓這名高中生也可以身兼數職呢?答案是多繼承,也就是同時讓其繼承兩個或更多的父類。
點選檢視程式碼
class HighSchoolStudent(Student,Programmer):
    pass
現在高中生也可以寫程式碼了。但是一個新的問題出現了,學生類和程式設計師類都有一個屬性gender,高中生會有兩個同名屬性嗎?答案是不會的。同名情況下,高中生只會獲得繼承順序靠前的父類的屬性和方法。我們可以用類名.__mro__ 屬性來檢視繼承的順序。 繼承的內容到這裡基本就告一段落了,總結一下,繼承主要是關於子類呼叫父類的內容,這個過程中可以重寫其內容。私有屬性或方法可以讓我們不對外暴露,同樣也可以讓子類無法直接繼承。

相關文章