Menu
Coddy logo textTech

Verknüpfung mit __index

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

Sie haben eine Prototyp-Tabelle mit Eigenschaften und Methoden, aber wie bringen Sie ein neues Objekt dazu, diese tatsächlich zu verwenden? Die Antwort liegt in der Metamethode __index.

Wenn Sie auf einen Schlüssel zugreifen, der in einer Tabelle nicht existiert, gibt Lua normalerweise nil zurück. Wenn die Tabelle jedoch eine Metatabelle mit einem __index-Feld hat, sucht Lua stattdessen dort. Indem Sie __index so einstellen, dass es auf Ihren Prototyp zeigt, werden alle fehlenden Schlüssel automatisch im Prototyp gefunden:

local Dog = {
    species = "Canis familiaris",
    legs = 4
}

function Dog:bark()
    print("Woof!")
end

-- Erstelle eine leere Instanz
local myDog = {}

-- Verknüpfe sie mit dem Prototyp
setmetatable(myDog, { __index = Dog })

print(myDog.species)  -- Ausgabe: Canis familiaris
myDog:bark()          -- Ausgabe: Woof!

Die Tabelle myDog ist komplett leer, dennoch funktioniert der Zugriff auf myDog.species. Wenn Lua species in myDog nicht findet, prüft es das __index der Metatabelle und findet es in Dog.

Dies ist die Grundlage der objektorientierten Programmierung in Lua. Die Instanz kann ihre eigenen eindeutigen Daten haben, während gemeinsames Verhalten im Prototyp lebt. In der nächsten Lektion lernst du, wie du dieses Muster in eine saubere Konstruktorfunktion verpackst.

challenge icon

Aufgabe

Einfach

Jetzt wollen wir die __index-Metamethode in die Praxis umsetzen! Du wirst einen Prototyp erstellen und eine Instanz damit verknüpfen, sodass die Instanz auf Eigenschaften und Methoden zugreifen kann, die sie nicht direkt besitzt.

Du wirst deinen Code in zwei Dateien organisieren:

  • Robot.lua: Definiere eine Robot-Prototyp-Tabelle mit:
    • Einem model-Feld, das auf "RX-100" gesetzt ist
    • Einem batteryLevel-Feld, das auf 100 gesetzt ist
    • Einer :status()-Methode, die den aktuellen Zustand des Roboters ausgibt
    Gib die Tabelle am Ende der Datei zurück.
  • main.lua: Binde das Robot-Modul ein (require), erstelle dann eine leere Instanz-Tabelle und verknüpfe sie mit dem Robot-Prototyp unter Verwendung von setmetatable mit __index. Dies ermöglicht deiner leeren Instanz, auf alles vom Prototyp zuzugreifen.

Du erhältst eine Eingabe: einen Namen, den du deiner Roboter-Instanz zuweisen sollst.

Nachdem du die Instanz mit dem Prototyp verknüpft hast:

  1. Weise den eingegebenen Namen dem name-Feld deiner Instanz zu (dieser wird für die Instanz eindeutig)
  2. Rufe die :status()-Methode für deine Instanz auf

Deine :status()-Methode sollte in genau diesem Format drucken:

[name] ([model]) - Battery: [batteryLevel]%

Wenn die Eingabe zum Beispiel Sparky ist, sollte die Ausgabe wie folgt lauten:

Sparky (RX-100) - Battery: 100%

Beachte, dass die Instanz ihren eigenen name hat, aber über die __index-Verknüpfung auf model und batteryLevel vom Prototyp zugreift.

Spickzettel

Die __index-Metamethode ermöglicht es Objekten, Eigenschaften und Methoden von einer Prototyp-Tabelle zu erben.

Wenn Sie auf einen Schlüssel zugreifen, der in einer Tabelle nicht existiert, prüft Lua, ob die Tabelle eine Metatabelle mit einem __index-Feld hat. Falls ja, sucht Lua nach dem Schlüssel in der durch __index angegebenen Tabelle.

Um eine Instanz mit einem Prototyp zu verknüpfen:

local Prototype = {
    property = "value"
}

function Prototype:method()
    print("Method called")
end

-- Erstelle eine Instanz
local instance = {}

-- Mit Prototyp über __index verknüpfen
setmetatable(instance, { __index = Prototype })

-- Auf Prototyp-Eigenschaften und -Methoden zugreifen
print(instance.property)  -- Ausgabe: value
instance:method()         -- Ausgabe: Method called

Die Instanz-Tabelle kann leer sein, dennoch kann sie auf alle Eigenschaften und Methoden des Prototyps zugreifen. Die Instanz kann auch eigene, einzigartige Eigenschaften haben, die den Prototyp überschreiben oder erweitern.

Dieses Muster ist die Grundlage der objektorientierten Programmierung in Lua, bei der Instanzen das Verhalten eines Prototyps teilen, während sie ihre eigenen, einzigartigen Daten beibehalten.

Probier es selbst

-- Eingabe lesen
local name = io.read()

-- Das Robot-Modul anfordern
local Robot = require('Robot')

-- TODO: Eine leere Instanz-Tabelle erstellen

-- TODO: Die Instanz mit dem Robot-Prototyp verknüpfen, indem setmetatable mit __index verwendet wird

-- TODO: Den eingegebenen Namen dem Namensfeld deiner Instanz zuweisen

-- TODO: Die Methode :status() auf deiner Instanz aufrufen
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