Recherche…


Polymorphisme de base

Le polymorphisme est la capacité à exécuter une action sur un objet quel que soit son type. Ceci est généralement implémenté en créant une classe de base et en ayant deux ou plusieurs sous-classes qui implémentent toutes des méthodes avec la même signature. Toute autre fonction ou méthode manipulant ces objets peut appeler les mêmes méthodes, quel que soit le type d'objet sur lequel elle opère, sans avoir à effectuer au préalable une vérification de type. Dans la terminologie orientée objet, lorsque la classe X étend la classe Y, alors Y est appelée classe super ou classe de base et X est appelée sous-classe ou classe dérivée.

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)

Nous devrions voir cette sortie:

Aucun
4
6,0

Que se passe-t-il sans polymorphisme?
Sans polymorphisme, une vérification de type peut être requise avant d'effectuer une action sur un objet pour déterminer la méthode correcte à appeler. L' exemple de compteur suivant exécute la même tâche que le code précédent, mais sans l'utilisation du polymorphisme, la fonction get_area() doit faire plus de travail.

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)

Nous devrions voir cette sortie:

4
6,0

Note importante
Notez que les classes utilisées dans l'exemple du compteur sont des classes "new style" et héritent implicitement de la classe d'objet si Python 3 est utilisé. Le polymorphisme fonctionnera à la fois dans Python 2.x et 3.x, mais le code du contre-exemple du polymorphisme générera une exception s'il est exécuté dans un interpréteur Python 2.x en raison du type (input_obj). name renverra "instance" au lieu du nom de la classe si elles n'héritent pas explicitement de l'objet, ce qui entraîne que la zone n'est jamais affectée.

Duck Typing

Polymorphisme sans héritage sous forme de dactylographie comme disponible en Python grâce à son système de typage dynamique. Cela signifie que tant que les classes contiennent les mêmes méthodes, l'interpréteur Python ne les distingue pas, car la seule vérification des appels a lieu au moment de l'exécution.

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)

La sortie est la suivante:

Quaaaaaack!
Le canard a des plumes blanches et grises.
La personne imite un canard.
La personne prend une plume du sol et la montre.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow