基本多态性
多态性是对对象执行操作的能力,无论其类型如何。这通常通过创建基类并具有两个或更多子类来实现,这些子类都实现具有相同签名的方法。操作这些对象的任何其他函数或方法都可以调用相同的方法,而不管它在哪种类型的对象上操作,而无需先进行类型检查。在面向对象的术语中,当类 X 扩展类 Y 时,则 Y 称为超类或基类,X 称为子类或派生类。
class Shape:
"""
This is a parent class that is intended to be inherited by other classes
"""
def calculate_area(self):
"""
This method is intended to be overridden in subclasses.
If a subclass doesn't implement it but it is called, NotImplemented will be raised.
"""
raise NotImplemented
class Square(Shape):
"""
This is a subclass of the Shape class, and represents a square
"""
side_length = 2 # in this example, the sides are 2 units long
def calculate_area(self):
"""
This method overrides Shape.calculate_area(). When an object of type
Square has its calculate_area() method called, this is the method that
will be called, rather than the parent class' version.
It performs the calculation necessary for this shape, a square, and
returns the result.
"""
return self.side_length * 2
class Triangle(Shape):
"""
This is also a subclass of the Shape class, and it represents a triangle
"""
base_length = 4
height = 3
def calculate_area(self):
"""
This method also overrides Shape.calculate_area() and performs the area
calculation for a triangle, returning the result.
"""
return 0.5 * self.base_length * self.height
def get_area(input_obj):
"""
This function accepts an input object, and will call that object's
calculate_area() method. Note that the object type is not specified. It
could be a Square, Triangle, or Shape object.
"""
print(input_obj.calculate_area())
# Create one object of each class
shape_obj = Shape()
square_obj = Square()
triangle_obj = Triangle()
# Now pass each object, one at a time, to the get_area() function and see the
# result.
get_area(shape_obj)
get_area(square_obj)
get_area(triangle_obj)
我们应该看到这个输出:
无
4
6.0
没有多态性会发生什么?
如果没有多态性,则在对对象执行操作之前可能需要进行类型检查,以确定要调用的正确方法。以下计数器示例执行与前一代码相同的任务,但不使用多态,get_area()
函数必须执行更多工作。
class Square:
side_length = 2
def calculate_square_area(self):
return self.side_length ** 2
class Triangle:
base_length = 4
height = 3
def calculate_triangle_area(self):
return (0.5 * self.base_length) * self.height
def get_area(input_obj):
# Notice the type checks that are now necessary here. These type checks
# could get very complicated for a more complex example, resulting in
# duplicate and difficult to maintain code.
if type(input_obj).__name__ == "Square":
area = input_obj.calculate_square_area()
elif type(input_obj).__name__ == "Triangle":
area = input_obj.calculate_triangle_area()
print(area)
# Create one object of each class
square_obj = Square()
triangle_obj = Triangle()
# Now pass each object, one at a time, to the get_area() function and see the
# result.
get_area(square_obj)
get_area(triangle_obj)
我们应该看到这个输出:
4
6.0
重要说明请
注意,计数器示例中使用的类是新样式类,如果使用 Python 3,则隐式继承自对象类。多态性在 Python 2.x 和 3.x 中都有效,但是如果在 Python 2.x 解释器中运行,则多态性反例示例将引发异常,因为 type(input_obj)
。名称将返回,而不是类名实例,如果他们不明确地从 object 继承,导致从未被分配到区域。