Поиск…


Основной полиморфизм

Полиморфизм - это способность выполнять действие над объектом независимо от его типа. Обычно это достигается путем создания базового класса и наличия двух или более подклассов, которые реализуют методы с одной и той же сигнатурой. Любые другие функции или методы, которые манипулируют этими объектами, могут вызывать одни и те же методы независимо от того, к какому типу объекта он работает, не требуя сначала проверки типа. В объектно-ориентированной терминологии, когда класс 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). имя будет возвращать «экземпляр» вместо имени класса, если они явно не наследуются от объекта, в результате чего область никогда не назначается.

Утиная печать

Полиморфизм без наследования в виде утиной печати, доступный в Python из-за его системы динамического набора. Это означает, что до тех пор, пока классы содержат одни и те же методы, интерпретатор Python не различает их, так как только проверка вызовов происходит во время выполнения.

class Duck:
    def quack(self):
        print("Quaaaaaack!")
    def feathers(self):
        print("The duck has white and gray feathers.")

class Person:
    def quack(self):
        print("The person imitates a duck.")
    def feathers(self):
        print("The person takes a feather from the ground and shows it.")
    def name(self):
        print("John Smith")

def in_the_forest(obj):
    obj.quack()
    obj.feathers()

donald = Duck()
john = Person()
in_the_forest(donald)
in_the_forest(john)

Выход:

Quaaaaaack!
Утка имеет белые и серые перья.
Человек имитирует утку.
Человек берет перо с земли и показывает его.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow