Menu
Coddy logo textTech

Methoden überschreiben

Teil des Abschnitts Object Oriented Programming der Lua-Journey von Coddy — Lektion 37 von 70.

Bisher haben Kindklassen Methoden der Elternklasse geerbt und neue hinzugefügt. Aber was ist, wenn eine Kindklasse den gleichen Methodennamen mit anderem Verhalten benötigt? Dies wird als Method Overriding bezeichnet.

Wenn Sie eine Methode in einer untergeordneten Klasse mit demselben Namen wie in der übergeordneten Klasse definieren, hat die Version der untergeordneten Klasse Vorrang. Die Lookup-Chain von Lua prüft zuerst die untergeordnete Klasse – wenn sie die Methode dort findet, hört sie auf zu suchen.

local Animal = {}
Animal.__index = Animal

function Animal:new(name)
    local obj = {name = name}
    setmetatable(obj, Animal)
    return obj
end

function Animal:speak()
    print(self.name .. " makes a sound")
end

-- Dog überschreibt speak()
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})

function Dog:new(name)
    local obj = Animal.new(Animal, name)
    setmetatable(obj, Dog)
    return obj
end

function Dog:speak()
    print(self.name .. " barks: Woof!")
end

Nun reagiert jede Klasse unterschiedlich auf denselben Methodenaufruf:

local generic = Animal:new("Creature")
local buddy = Dog:new("Buddy")

generic:speak()  -- Ausgabe: Creature makes a sound
buddy:speak()    -- Ausgabe: Buddy barks: Woof!

Die :speak()-Methode von Dog ersetzt die Version der Elternklasse für Dog-Instanzen vollständig. Dies ermöglicht es Ihnen, spezialisiertes Verhalten zu erstellen und gleichzeitig ein konsistentes Interface beizubehalten – jedes Tier kann :speak() ausführen, aber jede Spezies tut dies auf unterschiedliche Weise.

challenge icon

Aufgabe

Einfach

Lass uns ein kleines Tierreich erschaffen, in dem verschiedene Kreaturen auf ihre eigene, einzigartige Weise sprechen! Du wirst eine Basisklasse Animal und zwei Kindklassen — Cat und Cow — erstellen, die jeweils die :speak()-Methode der Elternklasse mit ihrem eigenen spezialisierten Verhalten überschreiben.

Du wirst deinen Code auf vier Dateien verteilen:

  • Animal.lua: Deine Basisklasse mit einem :new(name)-Konstruktor, der den Namen des Tieres speichert. Füge eine :speak()-Methode hinzu, die den Namen des Tieres gefolgt von makes a sound ausgibt. Dies ist das Standardverhalten, das die Kindklassen überschreiben werden.
  • Cat.lua: Eine Kindklasse, die von Animal erbt. Ihr :new(name)-Konstruktor sollte den Eltern-Konstruktor aufrufen und dann die Metatabelle wieder mit Cat verknüpfen. Überschreibe die :speak()-Methode, damit Katzen etwas anderes sagen — gib den Namen der Katze gefolgt von meows: Meow! aus.
  • Cow.lua: Eine weitere Kindklasse, die von Animal erbt. Richte den Konstruktor genauso ein wie bei Cat. Überschreibe :speak(), sodass Kühe ihren Namen gefolgt von moos: Moo! ausgeben.
  • main.lua: Bring alles zusammen! Lies zwei Namen aus der Eingabe ein, erstelle eine Cat mit dem ersten Namen und eine Cow mit dem zweiten Namen. Rufe dann :speak() für beide auf, um zu demonstrieren, dass derselbe Methodenname je nach Klasse unterschiedliche Ausgaben erzeugt.

Du erhältst zwei Eingaben:

  1. Der Name der Katze
  2. Der Name der Kuh

Erstelle in deiner Hauptdatei beide Tiere und rufe :speak() zuerst für die Katze und dann für die Kuh auf.

Wenn die Eingaben zum Beispiel Whiskers und Bessie sind, sollte die Ausgabe wie folgt aussehen:

Whiskers meows: Meow!
Bessie moos: Moo!

Beachte, wie beide Tiere auf denselben :speak()-Methodenaufruf reagieren, aber jedes eine für seinen Typ spezifische Ausgabe erzeugt. Die Version der Cat ersetzt das generische "makes a sound"-Verhalten der Elternklasse vollständig, ebenso wie die Version der Cow. Dies ist Methoden-Überschreibung (Method Overriding) in Aktion — gleiche Schnittstelle, unterschiedliche Implementierungen!

Spickzettel

Method Overriding ermöglicht es einer Kindklasse, eine Methode mit demselben Namen wie eine Elternmethode zu definieren und so das Verhalten der Elternklasse durch eine spezialisierte Funktionalität zu ersetzen.

Wenn Lua nach einer Methode sucht, prüft es zuerst die Kindklasse. Wenn es die Methode dort findet, verwendet es diese Version und beendet die Suche in der Elternklasse.

Grundlegendes Beispiel für Method Overriding:

local Animal = {}
Animal.__index = Animal

function Animal:new(name)
    local obj = {name = name}
    setmetatable(obj, Animal)
    return obj
end

function Animal:speak()
    print(self.name .. " makes a sound")
end

-- Dog überschreibt speak()
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})

function Dog:new(name)
    local obj = Animal.new(Animal, name)
    setmetatable(obj, Dog)
    return obj
end

function Dog:speak()
    print(self.name .. " barks: Woof!")
end

Verwendung der überschriebenen Methode:

local generic = Animal:new("Creature")
local buddy = Dog:new("Buddy")

generic:speak()  -- Ausgabe: Creature makes a sound
buddy:speak()    -- Ausgabe: Buddy barks: Woof!

Die Methode der Kindklasse ersetzt die Version der Elternklasse für Instanzen dieser Kindklasse vollständig, was spezialisiertes Verhalten ermöglicht, während eine konsistente Schnittstelle über alle Klassen hinweg beibehalten wird.

Probier es selbst

-- main.lua: Alles zusammenführen

local Cat = require('Cat')
local Cow = require('Cow')

-- Eingabe lesen
local catName = io.read()
local cowName = io.read()

-- TODO: Erstelle eine Katze mit dem ersten Namen

-- TODO: Erstelle eine Kuh mit dem zweiten Namen

-- TODO: Rufe zuerst :speak() für die Katze auf, dann für die Kuh
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Object Oriented Programming