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.
Aufgabe
EinfachJetzt 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 eineRobot-Prototyp-Tabelle mit:- Einem
model-Feld, das auf"RX-100"gesetzt ist - Einem
batteryLevel-Feld, das auf100gesetzt ist - Einer
:status()-Methode, die den aktuellen Zustand des Roboters ausgibt
- Einem
main.lua: Binde das Robot-Modul ein (require), erstelle dann eine leere Instanz-Tabelle und verknüpfe sie mit dem Robot-Prototyp unter Verwendung vonsetmetatablemit__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:
- Weise den eingegebenen Namen dem
name-Feld deiner Instanz zu (dieser wird für die Instanz eindeutig) - 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 calledDie 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
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
1Das 'self'-Konzept
Tabellen mit FunktionenExplizites 'self'Die Doppelpunkt-SyntaxPunkt vs. DoppelpunktZusammenfassung – Beweglicher Punkt4Projekt: Digitale Bank
Projekt-SetupEinzahlungsmethode7Polymorphie & Überschreiben
Methoden überschreibenElternmethoden aufrufenDuck TypingGemeinsames InterfaceTyp prüfenRückblick - Mitarbeiterrollen10Projekt: Formen-Manager
Projekt-SetupRechteck-Klasse2Klassen-Prototyp-Muster
Das Prototyp-KonzeptVerknüpfung mit __indexDer :new()-KonstruktorAttribute initialisierenUnabhängige InstanzenZusammenfassung – Autofabrik5Operatorüberladung in OOP
Objekte addierenObjekte subtrahierenObjekte verkettenObjekte vergleichen (<, >)Rückblick – Wallet-Mathematik3Objektzustand und -verhalten
InstanzvariablenGetter-MethodenSetter-MethodenBerechnete EigenschaftenStrings formatierenGleichheitsprüfungenZusammenfassung – Studentennote6Grundlagen der Vererbung
Das Vererbungs-SetupMethoden vererbenDen Konstruktor erweiternChild-Methoden hinzufügenGemeinsam vs. EinzigartigZusammenfassung - Formen-Hierarchie9Komposition & Mixins
Has-A-BeziehungDelegationEinfache MixinsAnwendung mehrerer MixinsMixins vs. VererbungZusammenfassung – Roboter-Montage12Abschluss-Herausforderungen
Wiederholung - InventarsystemWiederholung - BenutzerverwaltungWiederholung - Score-TrackerFinaler OOP-Check