基本多型性

多型性是對物件執行操作的能力,無論其型別如何。這通常通過建立基類並具有兩個或更多子類來實現,這些子類都實現具有相同簽名的方法。操作這些物件的任何其他函式或方法都可以呼叫相同的方法,而不管它在哪種型別的物件上操作,而無需先進行型別檢查。在物件導向的術語中,當類 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 繼承,導致從未被分配到區域。