多态

Python SELF ZH
第 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()

重要! 请阅读以下内容——这很重要。

如果我们在FullTimeEmployee类中调用方法print_salary(),那么将调用基类的方法,因为在此类中没有定义该方法。

但是这个方法print_salary()将会调用self对象的get_salary()方法,而self的类型是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: No arguments

也可以考虑传递数据的类型——只需进行类型检查即可:


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: Help instruction: a and b should be int or float

如果传递的数据类型不正确,可以输出说明或甚至是在网上的文档链接——这也是一种很流行的解决方案。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION