8.1 多型
多型是物件導向程式設計 (OOP) 的基本概念之一,它允許不同類別的物件 使用相同的介面。
在Python中,多型是透過動態型別和繼承來達成的。多型的一個重要方面是方法重載和 用子類別的方法取代基類的方法。
多型的基本概念:
不同物件使用統一介面:
多型允許不同類別的物件使用統一的介面,這些物件可以有不同的方法實作。
動態型別:
在Python中,變數的型別是在執行期間決定的,這允許函數以支援所需介面的任何類別的物件運作。
繼承:
允許建立類別階層,子類別繼承基類的屬性和方法,但可以針對其特定功能重新定義它們。
多型範例:
簡單的多型範例:所有三個類別都有名為move()的方法。這意味著我們可以寫出能同時運作這些物件的代碼。
class Car:
def move(self):
pass
class Human:
def move(self):
pass
class Bird:
def move(self):
print("嘎!")
car = Car()
human = Human()
bird = Bird()
for it in [car, human, bird]:
it.move()
在這種情況下,「共同介面」是方法名稱,或者如果該方法有參數,則是其簽名。
8.2 方法覆寫
多型通常與繼承一起使用以建立類別階層,其中基類定義了共同介面,而子類別實作特定細節。
class Employee:
def get_salary(self):
return 1000
class FullTimeEmployee(Employee):
def get_salary(self):
return 5000
class PartTimeEmployee(Employee):
def get_salary(self):
return 3000
class Intern(Employee):
pass
def print_salary(employee):
print(employee.get_salary())
employees = [FullTimeEmployee(), PartTimeEmployee(), Intern()]
for employee in employees:
print_salary(employee)
這個例子類似於前一個,但有一個重要的不同點——我們的類別不必一定要有方法get_salary,因為基類中總是有這個方法。現在所有類別的「共同介面」不只是方法get_salary(),而是類別Employee及其所有方法和屬性。
8.3 呼叫子類別的方法
仔細看看下面的代碼:
我們呼叫的方法print_salary(),只存在於基類Employee中,而它從基類呼叫另一個基類的方法——get_salary()。那麼,什麼薪水會顯示在螢幕上呢?
class Employee:
def print_salary(self):
salary = self.get_salary()
print(salary)
def get_salary(self):
return 1000
class FullTimeEmployee(Employee):
def get_salary(self):
return 5000
class PartTimeEmployee(Employee):
def get_salary(self):
return 3000
class Intern(Employee):
pass
employees = [FullTimeEmployee(), PartTimeEmployee(), Intern()]
for employee in employees:
employee.print_salary()
重要! 請閱讀下面的內容——這很重要。
如果我們呼叫方法print_salary(),例如對類別FullTimeEmployee,那麼將呼叫基類的方法,因為該類別本身沒有宣告這個方法。
但是這個方法print_salary()會呼叫物件self上方法get_salary(),其類型為FullTimeEmployee,而不是Employee。因此,將會呼叫類別FullTimeEmployee中的方法get_salary()!
更進一步的是,類別FullTimeEmployee可以呼叫基類的方法get_salary()以滿足自己的需求。例如,我們想以基礎薪資的百分比來計算薪水:
class FullTimeEmployee(Employee):
def get_salary(self):
base_salary = super().get_salary()
return base_salary * 5
# 500%
class PartTimeEmployee(Employee):
def get_salary(self):
base_salary = super().get_salary()
return base_salary * 3 # 300%
8.4 方法重載
Python中的方法重載(method overloading)是建立多個具有相同名稱但不同參數的方法的能力。然而,Python中不支持像C++或Java那樣的純方法重載。
在Python中,可以透過使用默認參數、*args和**kwargs來模擬方法重載。
方法重載範例
我們可以實作一個函數,其行為將取決於傳入參數的數量。可以用不同的方式來實作,例如:
class Example:
def display(self, a=None, b=None):
if a is not None and b is not None: print(a, b)
elif a is not None: print(a)
else: print("沒有參數")
obj = Example()
obj.display(1, 2) # Output: 1 2
obj.display(1) # Output: 1
obj.display() # Output: 沒有參數
還可以考慮傳入數據的類型——只需進行類型檢查:
class Example:
def mod(self, a, b):
if type(a) == int and type(b) == int: print(a % b)
elif type(a) == float or type(b) == float: print(round(a / b))
else: print("說明:a 和 b 應該是 int 或 float")
obj = Example()
obj.mod(5, 2) # Output: 1
obj.mod(5.0, 2) # Output: 2
obj.mod("5", 2) # Output: 說明:a 和 b 應該是 int 或 float
如果傳入的數據類型不正確,可以輸出指引或甚至互聯網上的文檔連結——這也是非常流行的解決方案。
GO TO FULL VERSION