Zum Inhalt

iMooX und Zoo

iMooX Test Lektion 4

Übersicht

  • Thema: Vererbung und Polymorphismus in Python
  • Konzepte:
  • Eltern- und Kindklassen
  • Erweiterung von Methoden der Elternklasse
  • Mehrfachvererbung

Erklärung der Begriffe

  1. Eltern- und Kindklassen:

  2. Elternklasse (**Animal**): Definiert gemeinsame Eigenschaften und Methoden für alle abgeleiteten Klassen.

  3. Kindklassen (**Duck**, **Dog**, **Beaver**): Erben von der Elternklasse und können spezifische Eigenschaften oder Methoden hinzufügen.

  4. Methoden der Elternklasse erweitern:

  5. In den Kindklassen können Methoden der Elternklasse überschrieben oder durch super() aufgerufen und erweitert werden.

  6. Mehrfachvererbung:

  7. Python erlaubt eine Klasse, von mehreren Elternklassen zu erben, was in komplexeren Szenarien nützlich ist.


Python-Code Analyse

Elternklasse: Animal

  • Attribute:
  • __name: Name des Tiers (privates Attribut).
  • __age: Alter des Tiers (privates Attribut).
  • Methoden:
  • **__init__**: Konstruktor, initialisiert name und age.
  • **get_name**: Gibt den Namen des Tiers zurück.
  • **get_age**: Gibt das Alter des Tiers zurück.
  • **eat**: Gibt eine Nachricht aus, dass das Tier frisst.
  • **say_hello**: Gibt eine allgemeine Begrüßung aus.

Kindklassen: Duck, Dog, Beaver

  • Erben von der Elternklasse Animal.

  • Jede Kindklasse kann:

  • Methoden der Elternklasse überschreiben.

  • Neue, spezifische Methoden hinzufügen.


Vorteile von Vererbung und Polymorphismus

  1. Wiederverwendbarkeit: Gemeinsame Funktionen müssen nicht wiederholt werden.
  2. Erweiterbarkeit: Kindklassen können angepasst werden, ohne die Elternklasse zu ändern.
  3. Flexibilität: Polymorphismus erlaubt die Verwendung eines einheitlichen Interfaces für verschiedene Objekte.

Fragen iMooX Test zsmfassung


  1. Was ist der Anwendungsbereich, auch Scope genannt?

Der programmbereich, in dem eine Variable gültig ist.


  1. Welche Vorteile hat das Verwenden von Verkapselung in der objektorientierten Programmierung?

Es gewährleistet, dass Daten nur innerhalb des Objekts modifiziert werden können.

Es stellt sicher, dass Attribute und Methoden nur von innen aufgerufen werden können.


  1. Welche Aussagen bezogen auf das Thema Vererbung sind richtig?

Vererbung kann die Wartbarkeit verbessern.

Zu viel Vererbung kann unübersichtliche Hierarchien schaffen.

Vererbung hilft uns dabei Code besser zu strukturieren.


  1. Was ist ein Objekt in der objektorientierten Programmierung?

Eine Instanz einer Klasse, die tatsächliche Daten enthält.


  1. Welche Wort fehlt? OOP ist ein Programmierparadigma, bei dem das Softwaredesign um_herum organisiert wird.

Wie nennt man die spezielle Methode, die bei der Erstellung eines Objektes der Klasse automatisch aufgerufen wird?

Konstruktor


  1. Welches Schlüsselwort signalisiert in Python die Definition einer Klasse?

class


  1. Was ist der Konstruktor einer Klasse?

Eine spezielle Methode, die bei der Erstellung eines Objektes automatisch aufgerufen wird.


  1. Wie werden Objekte in Python instanziiert?

Mit dem Namen der Klasse und Klammern


  1. Wofür wird Verkapselung verwendet?

Mit Verkapselung wollen wir den Zugriff auf Objekte steuern. 

Mit Verkapselung wollen wir Code verstecken der nicht relevant ist für andere Objekte


  1. Kann in Python auf private Variablen von außen Zugegriffen werden?

Ja, wenn wir den vollen Namen kennen.


  1. Welches Schlüsselwort signalisiert in Python die Definition eines Konstruktors?

__init_____()


  1. Was sind die Vorteile der Verwendung von Vererbung?

Methoden aus der Basisklasse können überschrieben werden

Bessere Code Wartbarkeit


  1. Was ist eine Elternklasse?

Eine Klasse, von der eine andere Klasse ableitet


  1. Welches Schlüsselwort wird verwendet um die Eltern-Form einer Methode aufzurufen?

super


  1. Was ist Mehrfachvererbung?

Eine Kindklasse, die mehrere Elternklassen hat.


  1. Was ist Method-Overriding?

Das Überschreiben einer Methode der Elternklasse in der Kinderklasse


  1. Was ist eine Kinderklasse?

Eine Klasse, die von einer anderen Klasse abgeleitet wurde.


Zootiere

Aufgabe 1:

Ich habe 3 Dateien erstellt in der main.py datei gibt es den folgenden Code:

# Import von ZooTier und KaiserPinguin
from zootier import ZooTier
from kaiserpinguin import KaiserPinguin

# Erzeugen eines allgemeinen ZooTiers
zootier = ZooTier("Säuger", "sehr viele", "allgemeines Tier", "Säugetiere")

# Zugriff auf die Methoden von ZooTier
zootier.tier_info()  # Ausgabe der allgemeinen Informationen
print(zootier.tier_laut())  # Ausgabe der Tierlaute

# Erzeugen eines KaiserPinguins
kaiser_pinguin = KaiserPinguin("Kaiser Pinguin", 5, "Pinguin", "Vögel", "schwarz-weiß")

# Zugriff auf die Methoden des KaiserPinguins
print(kaiser_pinguin.tier_info())  # Ausgabe der erweiterten Informationen
print(kaiser_pinguin.tier_laut())  # Ausgabe der spezifischen Tierlaute
kaiser_pinguin.fliegen()  # Ausgabe der speziellen Methode

in zootier.py:

# Elternklasse ZooTier in zootier.py
class ZooTier:
    def __init__(self,name,alter,tierart,tierklasse):
        self._name = name
        self._alter = alter
        self._tierart = tierart
        self._tierklasse = tierklasse

    # Getter- und Setter-Methoden
    def get_name(self):
        return self._name

    def get_alter(self):
        return self._alter

    def set_name(self, name):
        self._name = name

    def set_alter(self, alter):
        self._alter = alter

    # Tierlaute und Tierinfo
    def tier_laut(self):
        return "Es gibt Tiere, welche keine für uns Menschen hörbaren Laute von sich geben. Wie z.B. die Fledermaus. Andere wiederum können sehr laut sein. Wie z.B. der Löwe oder der Elefant."

    def tier_info(self):
        print (f"Ich bin ein {self._tierart} aus der Familie der {self._tierklasse}. Mein Name ist {self._name} und ich bin {self._alter} Jahre alt.")

und das kaiserpinguin.py:

from zootier import ZooTier

class KaiserPinguin(ZooTier):  # Vererbung von ZooTier
    def __init__(self, name, alter, tierart, tierklasse, gefiederfarbe="unbekannt"):
        super().__init__(name, alter, tierart, tierklasse)
        self._gefiederfarbe = gefiederfarbe

    # Überschreiben der tier_laut Methode
    def tier_laut(self):
        return "Krrrr Krrr Krrrrrr"

    # Ergänzen der tier_info Methode
    def tier_info(self):
        allgemeine_info = super().tier_info()  # Aufruf der Elternmethode
        return f"{allgemeine_info} Mein Gefieder ist {self._gefiederfarbe}."

    # Eine zusätzliche Methode für den KaiserPinguin
    def fliegen(self):
        print("Sorry, aber fliegen kann ich einfach nicht! 😢")

Aufgabe 2:

from zootier import ZooTier

zootier = ZooTier("Säuger", "sehr viele", "allgemeines Tier", "Säugetiere") 

print(zootier.tier_info())
print(zootier.tier_laut())

Aufgabe 3:

# Import von ZooTier und KaiserPinguin
from kaiserpinguin import KaiserPinguin

# Instanziierung von Franzl
franzl = KaiserPinguin(name="Franzl", alter=3, tierart="KaiserPinguin", tierklasse="Vögel")

# Instanziierung von Gretl
gretl = KaiserPinguin(name="Gretl", alter=8, tierart="KaiserPinguin", tierklasse="Vögel")

# Berechnung des Gesamtalters
alter_gesamt = franzl.get_alter() + gretl.get_alter()  # Getter-Methode für das Alter verwenden
print(f"Alter beider Kaiserpinguine = {alter_gesamt}")

Aufgabe 4:

Bei main.py muss man es so anpassen:

from kaiserpinguin import KaiserPinguin
from zootier import ZooTier

# Erzeugung eines allgemeinen ZooTier-Objekts
zootier = ZooTier("Säuger", "sehr viele", "allgemeines Tier", "Säugetiere")
print(zootier.tier_info())  # Ausgabe der allgemeinen Tierinformation

# Erzeugen eines KaiserPinguin-Objekts
kaiserpinguin_franzl = KaiserPinguin("Franzl", 3, "Pinguin", "Vögel", "schwarz-weiss")
print(kaiserpinguin_franzl.tier_info())  # Ausgabe der spezifischen Informationen des KaiserPinguins
print(kaiserpinguin_franzl.tier_laut())  # Ausgabe des Lautes des KaiserPinguins

# Ändern des Alters von Gretl
kaiserpinguin_gretl = KaiserPinguin("Gretl", 7, "Pinguin", "Vögel", "schwarz-weiss")
kaiserpinguin_gretl.alter = 10  # Änderung des Alters über den Setter
print(kaiserpinguin_gretl.tier_info())  # Ausgabe der geänderten Info

# Versuch, das Alter unter den erlaubten Wert zu setzen
kaiserpinguin_gretl.alter = 3  # Dies wird durch den Setter blockiert
print(kaiserpinguin_gretl.tier_info())  # Info bleibt unverändert

Also Output erhalten wir folgenden Text:

Ich bin ein allgemeines Tier aus der Familie der Säugetiere. Mein Name ist Säuger und ich bin sehr viele Jahre alt.
None
Ich bin ein Pinguin aus der Familie der Vögel. Mein Name ist Franzl und ich bin 3 Jahre alt. Mein Gefieder ist schwarz-weiss.
None
Krrrr Krrr Krrrrrr
Ich bin ein Pinguin aus der Familie der Vögel. Mein Name ist Gretl und ich bin 10 Jahre alt. Mein Gefieder ist schwarz-weiss.
None
Das Alter kann nicht unter 5 Jahren geändert werden.
Ich bin ein Pinguin aus der Familie der Vögel. Mein Name ist Gretl und ich bin 10 Jahre alt. Mein Gefieder ist schwarz-weiss.
None
Begriff Beschreibung Codebezug
super() Zugriff auf Methoden/Attribute der Elternklasse. super().__init__(name, alter, tierart, tierklasse) ruft Elternkonstruktor auf.
__init__() Konstruktor zur Initialisierung von Objekten. def __init__(self, name, alter, tierart, tierklasse): initialisiert Attribute.
Getter/Setter Ermöglichen den Zugriff auf private Attribute. def get_name(self): return self._name gibt den Namen zurück.
Vererbung Kindklasse erbt Methoden/Attribute der Elternklasse. class KaiserPinguin(ZooTier): zeigt, dass KaiserPinguin von ZooTier erbt.
Methode überschreiben Anpassen von Methoden der Elternklasse in der Kindklasse. def tier_laut(self): return "Krrrr Krrr Krrrrrr" überschreibt tier_laut in ZooTier.
Polymorphismus Gleiche Methodennamen, aber unterschiedliche Implementierungen je nach Objekt. kaiser_pinguin.tier_laut() gibt "Krrrr Krrr Krrrrrr" aus, während zootier.tier_laut() andere Laute ausgibt.
Kapselung Verstecken von Attributen und Zugriff nur über Methoden. _name und _alter sind private Attribute, auf die nur über Getter/Setter zugegriffen wird.

Was unterscheidet alter von _alter von __alter in Python?
alter ist öffentlich, _alter ist geschützt und __alter ist privat durch Namensmangling.

Wie wird ein Attribut in C# gekapselt?
Mit private oder protected und über Getter/Setter zugänglich gemacht.

Wie verhindern Sie den direkten Zugriff auf das Alter von Gretl?
Durch den @property-Dekorator.

Wie können Sie das Alter des geschützten Attributs dennoch verändern?
Über einen Setter.

Aufgabe 5:

vorgegebener code

pinguin_liste = []

def pinguin_hinzufuegen(name, alter, tierart, tierklasse, gefiederfarbe):
    pinguin = KaiserPinguin(name, alter, tierart, tierklasse, gefiederfarbe)
    pinguin_liste.append(pinguin)

pinguin_hinzufuegen("Susl", 8, "Pinguin", "Vögel", "schwarz-weiß")
pinguin_hinzufuegen("Friedrich", 5, "Pinguin", "Vögel", "grau")
pinguin_hinzufuegen("Anna", 3, "Pinguin", "Vögel")

abändern damit wir ihn in 2 zeilen durchführen können

for pinguin in pinguin_liste:
    print(pinguin.tier_info())

main.py code:

# Definition der Klasse ZooTier
class ZooTier:
    def __init__(self, name, alter, tierart, tierklasse):
        self._name = name
        self._alter = alter
        self._tierart = tierart
        self._tierklasse = tierklasse

    # Getter- und Setter-Methoden
    def get_name(self):
        return self._name

    def get_alter(self):
        return self._alter

    def set_name(self, name):
        self._name = name

    def set_alter(self, alter):
        self._alter = alter

    # Tierlaute und Tierinfo
    def tier_laut(self):
        return "Es gibt Tiere, welche keine für uns Menschen hörbaren Laute von sich geben. Wie z.B. die Fledermaus. Andere wiederum können sehr laut sein. Wie z.B. der Löwe oder der Elefant."

    def tier_info(self):
        return f"Ich bin ein {self._tierart} aus der Familie der {self._tierklasse}. Mein Name ist {self._name} und ich bin {self._alter} Jahre alt."

# Definition der Klasse KaiserPinguin
class KaiserPinguin(ZooTier):
    def __init__(self, name, alter, tierart, tierklasse, gefiederfarbe="unbekannt"):
        super().__init__(name, alter, tierart, tierklasse)
        self._gefiederfarbe = gefiederfarbe

    # Überschreibung der Elternmethode für die Tierlaute
    def tier_laut(self):
        return "Krrrr Krrr Krrrrrr"

    # Die tier_info-Methode erweitern
    def tier_info(self):
        allgemeine_info = super().tier_info()
        return f"{allgemeine_info} Mein Gefieder ist {self._gefiederfarbe}."

    def fliegen(self):
        print("Sorry, aber fliegen kann ich einfach nicht! 😢")

# Eine Liste zur Speicherung der Instanzen erstellen
pinguin_liste = []

# Eine Funktion, um Pinguine zur Liste hinzuzufügen
def pinguin_hinzufuegen(name, alter, tierart, tierklasse, gefiederfarbe="unbekannt"):
    pinguin = KaiserPinguin(name, alter, tierart, tierklasse, gefiederfarbe)
    pinguin_liste.append(pinguin)

# Pinguine zur Liste hinzufügen, ohne Objektnamen zu kennen
pinguin_hinzufuegen("Susl", 8, "Pinguin", "Vögel", "schwarz-weiß")
pinguin_hinzufuegen("Friedrich", 5, "Pinguin", "Vögel", "grau")
pinguin_hinzufuegen("Anna", 3, "Pinguin", "Vögel")

# Liste durchlaufen und tier_info() für jedes Objekt aufrufen
for pinguin in pinguin_liste:
    print(pinguin.tier_info())

output wenn wir den code ausführen:

Ich bin ein Pinguin aus der Familie der Vögel. Mein Name ist Susl und ich bin 8 Jahre alt. Mein Gefieder ist schwarz-weiß.
Ich bin ein Pinguin aus der Familie der Vögel. Mein Name ist Friedrich und ich bin 5 Jahre alt. Mein Gefieder ist grau.
Ich bin ein Pinguin aus der Familie der Vögel. Mein Name ist Anna und ich bin 3 Jahre alt. Mein Gefieder ist unbekannt.