目录
多态性的实现方式
1. 方法重写(Method Overriding)
2. 使用基类类型的引用
多态性的应用
示例:图形绘制
关键点
总结
在面向对象编程中,多态性(Polymorphism)是指相同的操作可以作用于不同的对象,并且可以根据对象的类型表现出不同的行为。多态性使得程序具有更好的扩展性和灵活性。
在 Python 中,多态性的实现主要依赖于继承和方法重写。具体来说,多态性允许使用基类类型的引用来引用子类对象,并且在运行时调用子类的重写方法。
多态性的实现方式
1. 方法重写(Method Overriding)
在继承中,子类可以重写父类的方法。这是实现多态性的基础。
python">class Animal:def speak(self):raise NotImplementedError("Subclass must implement abstract method")class Dog(Animal):def speak(self):return "Woof!"class Cat(Animal):def speak(self):return "Meow!"# 创建对象
dog = Dog()
cat = Cat()# 调用方法
print(dog.speak()) # 输出: Woof!
print(cat.speak()) # 输出: Meow!
在这个例子中,Dog
和 Cat
类都重写了 Animal
类的 speak
方法。当调用 speak
方法时,具体的实现由具体的对象决定。
2. 使用基类类型的引用
多态性使得可以用基类类型的引用来引用子类对象,并且在运行时调用子类的重写方法。
python">class Animal:def speak(self):raise NotImplementedError("Subclass must implement abstract method")class Dog(Animal):def speak(self):return "Woof!"class Cat(Animal):def speak(self):return "Meow!"def animal_speak(animal: Animal):print(animal.speak())# 创建对象
dog = Dog()
cat = Cat()# 使用基类类型的引用
animal_speak(dog) # 输出: Woof!
animal_speak(cat) # 输出: Meow!
在这个例子中,animal_speak
函数接受一个 Animal
类型的参数,但在运行时,可以传入任何 Animal
的子类对象,并且会调用相应子类的 speak
方法。
多态性的应用
多态性在实际应用中非常有用,特别是在需要处理一组具有不同具体实现的对象时。
示例:图形绘制
假设我们有一个图形绘制程序,支持绘制不同类型的图形(如圆形、矩形)。可以使用多态性来实现这个需求。
python">class Shape:def draw(self):raise NotImplementedError("Subclass must implement abstract method")class Circle(Shape):def draw(self):return "Drawing a Circle"class Rectangle(Shape):def draw(self):return "Drawing a Rectangle"# 定义一个绘图函数
def draw_shape(shape: Shape):print(shape.draw())# 创建对象
circle = Circle()
rectangle = Rectangle()# 使用多态性
draw_shape(circle) # 输出: Drawing a Circle
draw_shape(rectangle) # 输出: Drawing a Rectangle
在这个例子中,不同的图形类(如 Circle
和 Rectangle
)都实现了 Shape
类的 draw
方法。使用多态性,可以通过 Shape
类型的引用来调用具体图形对象的 draw
方法。
多态性与鸭子类型
Python 是一种动态类型语言,除了通过继承实现多态性外,还可以通过鸭子类型(Duck Typing)实现多态性。鸭子类型是一种动态类型系统,在这种系统中,一个对象是否能使用取决于它是否具有所需的方法或属性,而不是它的实际类型。
在 Python 中,鸭子类型(Duck Typing)的概念来自一句谚语:“如果它走路像鸭子,叫声像鸭子,那么它就是一只鸭子。”也就是说,一个对象的类型和方法是否可以用并不取决于这个对象的实际类型,而是它是否具有某个方法或属性。
在传统的静态类型语言中,一个函数的参数类型通常是固定的,这种类型检查是在编译时进行的。而在 Python 这样的动态类型语言中,类型检查是在运行时进行的。因此,只要传入的对象具有所需的方法或属性,Python 就会认为它是合适的类型。
python">class Bird:def fly(self):return "Bird is flying"class Airplane:def fly(self):return "Airplane is flying"def let_it_fly(obj):print(obj.fly())# 创建对象
bird = Bird()
airplane = Airplane()# 使用鸭子类型实现多态性
let_it_fly(bird) # 输出: Bird is flying
let_it_fly(airplane) # 输出: Airplane is flying
在这个例子中,let_it_fly
函数不关心传入对象的类型,只要对象具有 fly
方法即可。
关键点
-
动态类型检查:
let_it_fly
函数不会在调用时检查obj
的实际类型。- 只要
obj
具有fly
方法,Python 就会调用它,而不关心obj
是哪种类型的实例。
-
适配不同对象:
- 在例子中,
Bird
类和Airplane
类都有fly
方法。 - 当我们传递
bird
(Bird
类的实例)或airplane
(Airplane
类的实例)给let_it_fly
函数时,Python 会调用各自的fly
方法,输出不同的结果。
- 在例子中,
-
灵活性:
- 这种方式使得函数可以适配更多类型的对象,只要这些对象具有所需的方法或属性,而不必严格继承自某个特定的类。