多态与多态性
多态指的是同一种事物的多种状态:水这种事物有多种不同的状态:冰,水蒸气
多态性的概念指出了对象如何通过他们共同的属性和动作来操作及访问,而不需考虑他们具体的类。
冰,水蒸气,都继承于水,它们都有一个同名的方法就是变成云,但是冰.变云(),与水蒸气.变云()是截然不同的过程,虽然调用的方法都一样
就列如动物有多种形态:猫,狗,猪
import abc
class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
@abc.abstractmethod
def talk(self):
pass
class cat(Animal): #动物的形态之一:猫
def talk(self):
print('say hello')
class Dog(Animal): #动物的形态之二:狗
def talk(self):
print('say wangwang')
class Pig(Animal): #动物的形态之三:猪
def talk(self):
print('say aoao')
文件有多种形态:文本文件,可执行文件
import abc
class File(metaclass=abc.ABCMeta): #同一类事物:文件
@abc.abstractmethod
def click(self):
pass
class Text(File): #文件的形态之一:文本文件
def click(self):
print('open file')
class ExeFile(File): #文件的形态之二:可执行文件
def click(self):
print('execute file')
多态性
什么是多态动态绑定?(在继承的背景下使用时,有时也称为多态性)
多态性是指在不考虑实例类型的情况下使用实例
在面向对象方法中一般是这样表述多态性:
向不同的对象发送同一条消息(obj.func():是调用了obj的方法func,又称为向obj发送了一条消息func),不同的对象在接收时会产生不同的行为(即方法)。
也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。
比如:老师.下课铃响了(),学生.下课铃响了(),老师执行的是下班操作,学生执行的是放学操作,虽然二者消息一样,但是执行的效果不同
多态性
Cat=cat()
dog=Dog()
pig=Pig()
#Cat、dog、pig都是动物,只要是动物肯定有talk方法
#于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
Cat.talk()
dog.talk()
pig.talk()
#更进一步,我们可以定义一个统一的接口来使用
def func(obj):
obj.talk()
在Python中,实现多态性有几种方法,以下是其中一些常见的方式:
1、方法重写
在Python中,子类可以重写其父类中的方法。这意味着同名的方法可以在不同的类中有不同的实现,从而实现多态性。
示例代码:
class Animal:
def make_sound(self):
pass
class Dog(Animal):
def make_sound(self):
print('Woof!')
class Cat(Animal):
def make_sound(self):
print('Meow!')
def animal_sounds(animal):
animal.make_sound()
dog = Dog()
cat = Cat()
animal_sounds(dog) # 输出 "Woof!"
animal_sounds(cat) # 输出 "Meow!"
在这个例子中,我们定义了一个名为Animal的基类,它有一个名为make_sound()的方法。然后我们定义了两个子类Dog和Cat,它们都重写了make_sound()方法,并且在调用该方法时输出不同的声音。最后,我们编写了一个名为animal_sounds()的函数,该函数接受任何Animal类型的参数,并调用其make_sound()方法。通过将不同类型的动物传递给该函数,我们可以实现多态性。
2、多继承
在Python中,一个类可以继承自多个类,从而获得来自多个父类的属性和方法。这使得一个类可以具有多种类型,并且可以根据需要进行类型转换。
示例代码:
class Shape:
def area(self):
pass
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class Triangle(Shape):
def __init__(self, base, height):
self.base = base
self.height = height
def area(self):
return 0.5 * self.base * self.height
class Square(Rectangle):
def __init__(self, side):
super().__init__(side, side)
def print_area(shape):
print('The area is:', shape.area())
rectangle = Rectangle(3, 4)
triangle = Triangle(2, 5)
square = Square(6)
print_area(rectangle) # 输出 "The area is: 12"
print_area(triangle) # 输出 "The area is: 5.0"
print_area(square) # 输出 "The area is: 36"
在这个例子中,我们定义了一个名为Shape的基类,并为其添加了一个名为area()的抽象方法。然后我们定义了两个子类Rectangle和Triangle,它们分别实现了area()方法以计算矩形和三角形的面积。接下来,我们定义了一个名为Square的子类,该子类继承自Rectangle,并重写了__init__()方法以使其只接受一个参数。最后,我们编写了一个名为print_area()的函数,该函数接受任何Shape类型的参数,并调用其area()方法以计算并打印其面积。通过将不同类型的形状传递给该函数,我们可以实现多态性。
3、抽象基类
Python中的抽象基类是指一个类,它只定义了一些方法的签名,而没有提供实际的实现。这使得我们可以定义一个接口,该接口可以被多个具有不同实现的类实现,并通过该接口调用它们。
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * (self.radius ** 2)
在这个例子中,我们先导入了 ABC 和 abstractmethod 模块。然后,我们定义了一个叫做 Shape 的 ABC 类,其中有一个抽象方法 area()。接着,我们定义了两个子类:Rectangle 和 Circle,并且都继承自 Shape。在每个子类中,我们都重写了 Shape 中的 area() 方法。最后,我们创建了不同的对象,并调用了它们各自实现的方法。
这些子类都必须实现 Shape 中定义的 area() 方法,否则会抛出一个 TypeError 异常。ABC 的作用在于强制规定了子类的设计,使得代码更加严谨和可维护。
使用 ABC 可以让我们写出更加通用和可扩展的代码,因为它强制要求所有子类都实现相同的接口,从而保证了代码的一致性和可预见性。同时,ABC 也提高了代码的可读性,因为它显式地声明了子类需要实现哪些方法。