多型

Python SELF TW
等級 16 , 課堂 2
開放

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

如果傳入的數據類型不正確,可以輸出指引或甚至互聯網上的文檔連結——這也是非常流行的解決方案。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION