对象继承 inheritance
开始使用 Python 的类别 class 去解决问题时,通常会遇到需要修改类别的状况,这往往会造成原始类别的复杂化或破坏原本的功能,这时就需要使用类别里“继承”的方式来进行处理,这篇教学将会介绍 Python 中的“继承”。
本篇使用的 Python 版本为 3.7.12,所有范例可使用 Google Colab 实作,不用安装任何软件 ( 参考:使用 Google Colab )
什么是继承 inheritance?
继承,就如同字面上的意思:父亲继承了爷爷的东西,儿子继承父亲的东西...不断继承下去,继承表示可以用既有的类别去建立一个新的类别,并加入一些新的东西或修改新的类别,当使用继承时,新的类别会自动使用旧的类别内所有的程序码。
下方的程序码,名为 son 的类别使用class son(father)”的语法,继承了 fatehr 的程序码,当 oxxo 为 son 时,就能够呼叫出 fatehr 的所有属性。
class father(): # fatehr 類別
def __init__(self):
self.eye = 2
self.ear = 2
self.nose = 1
self.mouth = 1
class son(father): # son 類別繼承了 fatehr 類別裡所有的方法
def language(self): # son 類別具有 language 的方法
print('chinese') # 從 father 繼承了五官,然後自己學會講中文
oxxo = son() # 設定 oxxo 為 son()
print(oxxo.eye) # 印出 2
oxxo.language() # 印出 chinese
继承时会覆写方法
在继承时,如果子类类别里某个方法的名称和父类别相同,则会完全复写父类别的方法,下面的程序码,son 类别使用了 init 的方法,就覆写了原本 fatehr 的 init 方法,导致读取 oxxo.ear 时发生错误 ( 因为 son 的方法里不存在 ear 的属性 )
class father():
def __init__(self):
self.eye = 2
self.ear = 2
self.nose = 1
self.mouth = 1
class son(father):
def __init__(self): # 使用了 __init 的方法
self.eye = 100
oxxo = son()
print(oxxo.eye) # 100
print(oxxo.ear) # 發生錯誤 'son' object has no attribute 'ear'
使用 super()
如果不想要覆写父类别的方法,又想要使用父类别的方法,就可以使用“super()”来实现,下方的程序码,使用 super() 继承了 father init 里所有的属性,然后再将 eye 的属性覆写为 100。
class father():
def __init__(self):
self.eye = 2
self.ear = 2
self.nose = 1
self.mouth = 1
class son(father):
def __init__(self):
super().__init__() # 使用 super() 繼承 father __init__ 裡所有屬性
self.eye = 100 # 如果屬性相同,則覆寫屬性
oxxo = son()
print(oxxo.eye) # 100
print(oxxo.ear) # 2
多重继承
继承不仅能进行单一继承,也可以进行多重继承,例如可以从爸爸身上继承基因,同时也可以从妈妈身上继承基因一般,下方的例子,son 从 father 继承了五官,从 mother 继承了 language 和 skill。
class father(): # father 類別
def __init__(self): # father 的方法
self.eye = 2
self.ear = 2
self.nose = 1
self.mouth = 1
class mother(): # mother 類別
def language(self): # mother 的方法
print('english')
def skill(self):
print('painting')
class son(father, mother): # 繼承 father 和 mother
def play(self): # son 自己的方法
print('ball')
oxxo = son()
print(oxxo.eye) # 2
oxxo.skill() # painting
oxxo.play() # ball
进行多重继承时,同样会有“覆写方法”的状况出现,而覆写方法的顺序是从“读取类别的顺序”决定,举例来说,下方的 c 和 d 两个类别,虽然都多重继承了 a 和 b,但因为读取的顺序不同,所以呈现的结果也会不同。
class a():
def says(self):
print('a')
class b():
def says(self):
print('b')
class c(a, b): # 先讀取 a 再 b,就會將 a 裡的方法,覆寫 b 裡同名的方法
pass
class d(b, a): # 先讀取 b 再 a,就會將 b 裡的方法,覆寫 a 裡同名的方法
pass
ccc = c()
ddd = d()
ccc.says() # a
ddd.says() # b
多层继承
继承里除了多重继承,也有“多层继承”的概念,就如同父亲继承了爷爷的东西,儿子继承父亲的东西,多层继承同样存在覆写方法的原则,如果遇到同名的方法就会覆写,除非使用 super() 的方法处理,下方的例子里, father 继承了 grandpa 的五官,son 又继承了 father 的方法,最后 son 就拥有 father 和 grandpa 所有的方法。
class grandpa():
def __init__(self):
self.eye = 2
self.ear = 2
self.nose = 1
self.mouth = 1
class father(grandpa):
def language(self):
print('english')
def skill(self):
print('painting')
class son(father):
def play(self):
print('ball')
oxxo = son()
print(oxxo.eye) # 2
oxxo.skill() # painting
oxxo.play() # ball
私有方法 ( 双底线 )
在实作一个类别的过程里,可能会遇到有些方法是该类别内部使用,不想让继承该类别的子类别可以用的,这时就需要建立“私有方法”,私有方法可以使用“雙底線 + 名稱”来建立,私有方法建立后,不论是从外部读取或是子类别的继承,都无法使用该方法,只有在该类别里的其他方法才能调用。
下方的程序码 grandpa 有一个 __money 的方法,但是除非知道 getMoney 的方法,不然都无法直接读取 ( 爷爷有一笔钱,除非你知道方法,不然无法继承成功 )。
class grandpa():
def __init__(self):
self.mouth = 1
def __money(self): # 建立一個私有方法 __money
print('$1000')
def getMoney(self): # 建立一個 getMoney 的方法,執行私有方法 __money
self.__money()
class father(grandpa):
def skill(self):
print('painting')
class son(father):
def play(self):
print('ball')
oxxo = son()
oxxo.getMoney() # $1000
oxxo.__money() # 發生錯誤 'son' object has no attribute '_money'
微信扫码关注
抖音扫码关注