Zoeken…


Fundamenteel polymorfisme

Polymorfisme is de mogelijkheid om een actie op een object uit te voeren, ongeacht het type. Dit wordt meestal geïmplementeerd door een basisklasse te maken en twee of meer subklassen te hebben die allemaal methoden met dezelfde handtekening implementeren. Elke andere functie of methode die deze objecten manipuleert, kan dezelfde methoden aanroepen, ongeacht het type object waarop het werkt, zonder eerst een typecontrole uit te voeren. In objectgeoriënteerde terminologie wanneer klasse X klasse Y uitbreidt, wordt Y superklasse of basisklasse genoemd en wordt X subklasse of afgeleide klasse genoemd.

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)

We zouden deze output moeten zien:

Geen
4
6.0

Wat gebeurt er zonder polymorfisme?
Zonder polymorfisme kan een typecontrole vereist zijn voordat een actie op een object wordt uitgevoerd om de juiste aan te roepen methode te bepalen. De volgende tegenvoorbeeld voert dezelfde taak als de vorige code, maar zonder het gebruik van polymorfisme, de get_area() functie moet meer werk te doen.

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)

We zouden deze output moeten zien:

4
6.0

Belangrijke notitie
Merk op dat de klassen die in het tellervoorbeeld worden gebruikt "nieuwe stijl" -klassen zijn en impliciet van de objectklasse erven als Python 3 wordt gebruikt. Polymorfisme werkt in zowel Python 2.x als 3.x, maar de tegenexample-code voor polymorfisme zal een uitzondering veroorzaken als het wordt uitgevoerd in een Python 2.x-interpreter omdat type (input_obj). name retourneert "instance" in plaats van de klassennaam als ze niet expliciet van het object erven, waardoor het gebied nooit wordt toegewezen.

Eend typen

Polymorfisme zonder overerving in de vorm van eenden typen zoals beschikbaar in Python vanwege het dynamische typsysteem. Dit betekent dat zolang de klassen dezelfde methoden bevatten, de Python-interpreter er geen onderscheid tussen maakt, omdat de enige controle van de oproepen tijdens runtime plaatsvindt.

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)

De output is:

Quaaaaaack!
De eend heeft witte en grijze veren.
De persoon imiteert een eend.
De persoon neemt een veer van de grond en laat het zien.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow