CodeGym /Kurse /Python SELF DE /Polymorphismus

Polymorphismus

Python SELF DE
Level 16 , Lektion 2
Verfügbar

8.1 Polymorphismus

Polymorphismus ist eines der Grundkonzepte der objektorientierten Programmierung (OOP), das es Objekten verschiedener Klassen ermöglicht, dasselbe Interface zu verwenden.

In Python wird Polymorphismus durch dynamische Typisierung und Vererbung erreicht. Ein wichtiger Aspekt des Polymorphismus ist die Überladung von Methoden und das Überschreiben von Methoden der Basisklasse durch Methoden der abgeleiteten Klasse.

Wichtige Konzepte des Polymorphismus:

Einheitliches Interface für verschiedene Objekte:

Polymorphismus ermöglicht die Verwendung eines einheitlichen Interfaces für Objekte verschiedener Klassen, die unterschiedliche Implementierungen von Methoden haben können.

Dynamische Typisierung:

In Python wird der Typ einer Variable zur Laufzeit bestimmt, was es einer Funktion ermöglicht, mit Objekten beliebiger Klassen zu arbeiten, sofern sie das erforderliche Interface unterstützen.

Vererbung:

Ermöglicht das Erstellen von Klassenhierarchien, bei denen Unterklassen die Eigenschaften und Methoden der Basisklasse erben, sie jedoch für ihre spezifische Funktionalität überschreiben können.

Beispiele für Polymorphismus:

Ein einfaches Beispiel für Polymorphismus: Alle drei Klassen haben eine Methode mit dem Namen move(). Das bedeutet, dass wir Code schreiben können, der mit diesen Objekten gleichzeitig funktioniert.


class Car:
    def move(self):
        pass
        
class Human:
    def move(self):
        pass
        
class Bird:
    def move(self):
        print("Krah!")
        
car = Car()
human = Human()
bird = Bird()
        
for it in [car, human, bird]:
    it.move()

In diesem Fall ist der "gemeinsame Interface" der Methodenname oder seine Signatur, wenn die Methode Parameter hat.

8.2 Methodenüberschreibung

Polymorphismus wird häufig zusammen mit Vererbung verwendet, um Klassenhierarchien zu erstellen, bei denen die Basisklasse ein gemeinsames Interface definiert und die Unterklassen spezifische Details implementieren.


class Employee:
    def get_salary(self):
        return 1000
        
class FullTimeEmployee(Employee):
    def get_salary(self):
        return 5000
        
class PartTimeEmployee(Employee):
    def get_salary(self):
        return 3000
        
class Intern(Employee):
    pass
        
def print_salary(employee):
    print(employee.get_salary())
        
employees = [FullTimeEmployee(), PartTimeEmployee(), Intern()]
        
for employee in employees:
    print_salary(employee)

Dieses Beispiel ähnelt dem vorherigen, hat jedoch einen wichtigen Unterschied – unsere Klassen müssen keine Methode get_salary haben, da sie immer in der Basisklasse vorhanden ist. Jetzt ist das "gemeinsame Interface" aller Klassen nicht nur die Methode get_salary(), sondern der Klasse Employee mit all ihren Methoden und Attributen.

8.3 Aufrufen von Methoden der abgeleiteten Klasse

Schaut euch den folgenden Code genau an:

Wir rufen die Methode print_salary() auf, die nur bei der Basisklasse Employee existiert, und die aus der Basisklasse eine andere Methode der Basisklasse aufruft – get_salary(). Welche Gehälter werden also auf dem Bildschirm angezeigt?


class Employee:
    def print_salary(self):
        salary = self.get_salary()
        print(salary)
        
    def get_salary(self):
        return 1000
        
class FullTimeEmployee(Employee):
    def get_salary(self):
        return 5000
        
class PartTimeEmployee(Employee):
    def get_salary(self):
        return 3000
        
class Intern(Employee):
    pass
        
employees = [FullTimeEmployee(), PartTimeEmployee(), Intern()]
        
for employee in employees:
    employee.print_salary()

Wichtig! Lest das, was unten steht — es ist wichtig.

Wenn wir die Methode print_salary() beispielsweise bei der Klasse FullTimeEmployee aufrufen, wird die Methode der Basisklasse aufgerufen, da so eine Methode in der eigenen Klasse nicht deklariert ist.

Aber diese Methode print_salary() wird die Methode get_salary() auf dem Objekt self aufrufen, welches den Typ FullTimeEmployee hat und nicht Employee. Deshalb wird genau die Methode get_salary() der Klasse FullTimeEmployee aufgerufen!

Darüber hinaus kann die Klasse FullTimeEmployee die Methode get_salary() der Basisklasse für ihre eigenen Zwecke aufrufen. Zum Beispiel, wenn wir das Gehalt in Prozent vom Basisgehalt berechnen wollen:


class FullTimeEmployee(Employee):
    def get_salary(self):
        base_salary = super().get_salary()
        return base_salary * 5  
      
  
      
  
      
  
# 500%
class PartTimeEmployee(Employee): def get_salary(self): base_salary = super().get_salary() return base_salary * 3 # 300%

8.4 Methodenüberladung

Methodenüberladung (method overloading) in Python ist die Fähigkeit, mehrere Methoden mit demselben Namen aber unterschiedlichen Parametern zu erstellen. Allerdings wird die Methodenüberladung in ihrer reinen Form in Python nicht unterstützt, wie es in anderen Sprachen der Fall ist (z.B. C++ oder Java).

In Python kann die Methodenüberladung durch die Verwendung von Standardargumenten, *args und **kwargs imitiert werden.

Beispiele für Methodenüberladung

Wir können eine Funktion implementieren, die sich je nach Anzahl der übergebenen Argumente unterschiedlich verhält. Dies kann auf verschiedene Weise erfolgen, zum Beispiel so:


class Example:
    def display(self, a=None, b=None):
        if a is not None and b is not None: print(a, b)
        elif a is not None: print(a)
        else: print("Keine Argumente")
        

obj = Example()
obj.display(1, 2)  # Ausgabe: 1 2
obj.display(1)  # Ausgabe: 1
obj.display()  # Ausgabe: Keine Argumente

Man kann auch den Typ der übergebenen Daten berücksichtigen – einfach einen Typencheck durchführen:


class Example:
    def mod(self, a, b):
        if type(a) == int and type(b) == int: print(a % b)
        elif type(a) == float or type(b) == float: print(round(a / b))
        else: print("Hilfsanweisung: a und b sollten int oder float sein")
        

obj = Example()
obj.mod(5, 2)  # Ausgabe: 1
obj.mod(5.0, 2)  # Ausgabe: 2
obj.mod("5", 2)  # Ausgabe: Hilfsanweisung: a und b sollten int oder float sein

Wenn falsche Datentypen übergeben werden, kann man eine Anweisung ausgeben oder sogar einen Link zur Dokumentation im Internet bereitstellen – das ist auch eine sehr beliebte Lösung.

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION