Python學習(七)面向對象 ——繼承和多態


Python 類的繼承和多態

 

  Python 類的繼承

    在OOP(Object Oriented Programming)程序設計中,當我們定義一個class的時候,可以從某個現有的class 繼承,新的class稱為子類(Subclass),而被繼承的class稱為基類、父類或超類(Base class、Super class)。

    我們先來定義一個class Person,表示人,定義屬性變量 name 及 sex (姓名和性別);

    定義一個方法print_title():當sex是male時,print man;當sex 是female時,print woman。參考如下代碼:

 1 class Person(object):
 2     def __init__(self,name,sex):
 3         self.name = name
 4         self.sex = sex
 5         
 6     def print_title(self):
 7         if self.sex == "male":
 8             print("man")
 9         elif self.sex == "female":
10             print("woman")
11 
12 class Child(Person):                            # Child 繼承 Person
13     pass
14             
15 May = Child("May","female")
16 Peter = Person("Peter","male")
17 
18 print(May.name,May.sex,Peter.name,Peter.sex)    # 子類繼承父類方法及屬性
19 May.print_title()
20 Peter.print_title()

    而我們編寫 Child 類,完全可以繼承 Person 類(Child 就是 Person);使用 class subclass_name(baseclass_name) 來表示繼承;

    繼承有什么好處?最大的好處是子類獲得了父類的全部屬性及功能。如下 Child 類就可以直接使用父類的 print_title() 方法

    實例化Child的時候,子類繼承了父類的構造函數,就需要提供父類Person要求的兩個屬性變量 name 及 sex:

    在繼承關系中,如果一個實例的數據類型是某個子類,那它也可以被看做是父類(May 既是 Child 又是 Person)。但是,反過來就不行(Peter 僅是 Person,而不是Child)。

    繼承還可以一級一級地繼承下來,就好比從爺爺到爸爸、再到兒子這樣的關系。而任何類,最終都可以追溯到根類object,這些繼承關系看上去就像一顆倒着的樹。比如如下的繼承樹: 

    

 

  isinstance()   及  issubclass()

    Python 與其他語言不同點在於,當我們定義一個 class 的時候,我們實際上就定義了一種數據類型。我們定義的數據類型和Python自帶的數據類型,比如str、list、dict沒什么兩樣。

    Python 有兩個判斷繼承的函數:isinstance() 用於檢查實例類型;issubclass() 用於檢查類繼承。參見下方示例:

class Person(object):
    pass

class Child(Person):                 # Child 繼承 Person
    pass

May = Child()
Peter = Person()    

print(isinstance(May,Child))         # True
print(isinstance(May,Person))        # True
print(isinstance(Peter,Child))       # False
print(isinstance(Peter,Person))      # True
print(issubclass(Child,Person))      # True

 

  Python 類的多態

     在說明多態是什么之前,我們在 Child 類中重寫 print_title() 方法:若為male,print boy;若為female,print girl

 1 class Person(object):
 2     def __init__(self,name,sex):
 3         self.name = name
 4         self.sex = sex
 5         
 6     def print_title(self):
 7         if self.sex == "male":
 8             print("man")
 9         elif self.sex == "female":
10             print("woman")
11 
12 class Child(Person):                # Child 繼承 Person
13     def print_title(self):
14         if self.sex == "male":
15             print("boy")
16         elif self.sex == "female":
17             print("girl")
18         
19 May = Child("May","female")
20 Peter = Person("Peter","male")
21 
22 print(May.name,May.sex,Peter.name,Peter.sex)
23 May.print_title()
24 Peter.print_title()

    當子類和父類都存在相同的 print_title()方法時,子類的 print_title() 覆蓋了父類的 print_title(),在代碼運行時,會調用子類的 print_title()

    這樣,我們就獲得了繼承的另一個好處:多態 

    多態的好處就是,當我們需要傳入更多的子類,例如新增 Teenagers、Grownups 等時,我們只需要繼承 Person 類型就可以了,而print_title()方法既可以直不重寫(即使用Person的),也可以重寫一個特有的。這就是多態的意思。調用方只管調用,不管細節,而當我們新增一種Person的子類時,只要確保新方法編寫正確,而不用管原來的代碼。這就是著名的“開閉”原則:

  •     對擴展開放(Open for extension):允許子類重寫方法函數
  •     對修改封閉(Closed for modification):不重寫,直接繼承父類方法函數

 

  子類重寫構造函數

     子類可以沒有構造函數,表示同父類構造一致;子類也可重寫構造函數;現在,我們需要在子類 Child 中新增兩個屬性變量:mother 和 father,我們可以構造如下(建議子類調用父類的構造方法,參見后續代碼):

 1 class Person(object):
 2     def __init__(self,name,sex):
 3     self.name = name
 4     self.sex = sex
 5 
 6 class Child(Person):                # Child 繼承 Person
 7     def __init__(self,name,sex,mother,father):
 8         self.name = name
 9         self.sex = sex
10         self.mother = mother
11         self.father = father
12 
13 May = Child("May","female","April","June")
14 print(May.name,May.sex,May.mother,May.father)    
Person

 

     若父類構造函數包含很多屬性,子類僅需新增1、2個,會有不少冗余的代碼,這邊,子類可對父類的構造方法進行調用,參考如下:

 1 class Person(object):
 2     def __init__(self,name,sex):
 3         self.name = name
 4         self.sex = sex
 5 
 6 class Child(Person):                          # Child 繼承 Person
 7     def __init__(self,name,sex,mother,father):
 8         Person.__init__(self,name,sex)        # 子類對父類的構造方法的調用
 9         self.mother = mother
10         self.father = father
11 
12 May = Child("May","female","April","June")
13 print(May.name,May.sex,May.mother,May.father)    

 

  多重繼承

    多重繼承的概念應該比較好理解,比如現在需要新建一個類 baby 繼承 Child , 可繼承父類及父類上層類的屬性及方法,優先使用層類近的方法,代碼參考如下:

 1 class Person(object):
 2     def __init__(self,name,sex):
 3         self.name = name
 4         self.sex = sex
 5         
 6     def print_title(self):
 7         if self.sex == "male":
 8             print("man")
 9         elif self.sex == "female":
10             print("woman")
11             
12 class Child(Person):
13     pass
14 
15 class Baby(Child):
16     pass
17 
18 May = Baby("May","female")        # 繼承上上層父類的屬性
19 print(May.name,May.sex)            
20 May.print_title()                 # 可使用上上層父類的方法
21 
22 
23 class Child(Person):                
24     def print_title(self):
25         if self.sex == "male":
26             print("boy")
27         elif self.sex == "female":
28             print("girl")
29             
30 class Baby(Child):
31     pass
32             
33 May = Baby("May","female")
34 May.print_title()                # 優先使用上層類的方法

 


免責聲明!

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



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