Instanzvariablen
Teil des Abschnitts Object Oriented Programming der Lua-Journey von Coddy — Lektion 12 von 70.
Willkommen zu einem neuen Kapitel, das sich darauf konzentriert, wie Objekte ihre internen Daten verwalten. Sie haben gelernt, Klassen und Instanzen zu erstellen – jetzt ist es an der Zeit zu untersuchen, wie jede Instanz ihren eigenen, einzigartigen Zustand speichert und verwaltet.
Instanzvariablen sind Felder, die exklusiv zu einem einzelnen Objekt gehören. Wenn Sie einen Wert an self.something innerhalb einer Methode oder eines Konstruktors zuweisen, leben diese Daten nur in dieser speziellen Instanz. Andere Objekte derselben Klasse haben ihre eigenen separaten Kopien.
Dies wird besonders wichtig, wenn komplexe Daten wie Tabellen gespeichert werden. Stellen Sie sich ein Inventarsystem vor, in dem jeder Charakter verschiedene Gegenstände trägt:
local Inventory = {}
Inventory.__index = Inventory
function Inventory:new()
local instance = {}
setmetatable(instance, self)
instance.items = {} -- Jede Instanz erhält ihre eigene leere Tabelle
return instance
end
function Inventory:addItem(item)
table.insert(self.items, item)
endDie entscheidende Zeile ist instance.items = {}. Durch das Erstellen einer neuen leeren Tabelle innerhalb des Konstruktors erhält jedes Inventar-Objekt seine eigene, separate Liste. Wenn Sie stattdessen items in der Klassentabelle selbst definieren würden, würden alle Instanzen versehentlich dieselbe Tabelle teilen – das Hinzufügen eines Schwertes zu einem Charakter würde es jedem geben!
local bag1 = Inventory:new()
local bag2 = Inventory:new()
bag1:addItem("Sword")
bag2:addItem("Potion")
print(#bag1.items) -- Ausgabe: 1
print(#bag2.items) -- Ausgabe: 1Jedes Inventar verwaltet seine eigene Sammlung. Dieses Muster findet immer dann Anwendung, wenn eine Instanz Daten verfolgen muss, die sich unabhängig ändern – Listen, Zähler oder jeder veränderliche Zustand, der für dieses Objekt spezifisch ist.
Aufgabe
EinfachLassen Sie uns ein ShoppingCart-System bauen, bei dem jeder Warenkorb seine eigene separate Liste von Produkten verwaltet. Dies wird demonstrieren, wie Instanzvariablen Daten zwischen Objekten isoliert halten – das Hinzufügen von Artikeln zu einem Warenkorb hat keine Auswirkungen auf einen anderen!
Sie werden Ihren Code in zwei Dateien organisieren:
ShoppingCart.lua: Definieren Sie IhreShoppingCart-Klasse, in der jede Instanz ihre eigeneproducts-Tabelle hat. Fügen Sie Folgendes hinzu:- Einen
:new()-Konstruktor, der eine leere Produktliste für jeden Warenkorb initialisiert - Eine
:addProduct(productName)-Methode, die ein Produkt zur Liste dieses Warenkorbs hinzufügt - Eine
:listProducts()-Methode, die jedes Produkt in einer separaten Zeile ausgibt
- Einen
main.lua: Binden Sie Ihr ShoppingCart-Modul ein und erstellen Sie zwei separate Warenkörbe. Fügen Sie jedem Warenkorb unterschiedliche Produkte hinzu, um zu beweisen, dass sie unabhängige Bestände führen.
Sie erhalten vier Eingaben:
- Erstes Produkt, das zu Warenkorb A hinzugefügt werden soll
- Zweites Produkt, das zu Warenkorb A hinzugefügt werden soll
- Erstes Produkt, das zu Warenkorb B hinzugefügt werden soll
- Zweites Produkt, das zu Warenkorb B hinzugefügt werden soll
In Ihrer Hauptdatei:
- Erstellen Sie zwei Warenkörbe:
cartAundcartB - Fügen Sie die ersten beiden Produkte zu
cartAhinzu - Fügen Sie die letzten beiden Produkte zu
cartBhinzu - Geben Sie
Cart A:aus und listen Sie dann die Produkte von Warenkorb A auf - Geben Sie
Cart B:aus und listen Sie dann die Produkte von Warenkorb B auf
Wenn die Eingaben beispielsweise Apple, Bread, Milk und Eggs sind, sollte die Ausgabe wie folgt aussehen:
Cart A:
Apple
Bread
Cart B:
Milk
EggsDenken Sie daran: Der Schlüssel liegt darin, products als neue leere Tabelle innerhalb des Konstruktors zu initialisieren. Dies stellt sicher, dass jede Warenkorb-Instanz ihre eigene separate Liste erhält, anstatt eine Tabelle über alle Warenkörbe hinweg zu teilen.
Spickzettel
Instanzvariablen sind Felder, die exklusiv zu einem einzelnen Objekt gehören. Wenn Sie einem Wert self.something innerhalb einer Methode oder eines Konstruktors zuweisen, existieren diese Daten nur in dieser speziellen Instanz.
Um Instanzvariablen zu erstellen, initialisieren Sie diese innerhalb des Konstruktors, indem Sie für jede Instanz eine neue Tabelle verwenden:
local Inventory = {}
Inventory.__index = Inventory
function Inventory:new()
local instance = {}
setmetatable(instance, self)
instance.items = {} -- Jede Instanz erhält ihre eigene leere Tabelle
return instance
end
function Inventory:addItem(item)
table.insert(self.items, item)
endDer entscheidende Punkt ist instance.items = {} – das Erstellen einer neuen leeren Tabelle innerhalb des Konstruktors stellt sicher, dass jedes Objekt seine eigenen, separaten Daten erhält. Wenn Sie items in der Klassentabelle selbst definiert hätten, würden alle Instanzen dieselbe Tabelle teilen.
local bag1 = Inventory:new()
local bag2 = Inventory:new()
bag1:addItem("Sword")
bag2:addItem("Potion")
print(#bag1.items) -- Output: 1
print(#bag2.items) -- Output: 1Jede Instanz verwaltet ihre eigene Sammlung unabhängig voneinander. Dieses Muster gilt für jeden veränderlichen Zustand, der für ein Objekt einzigartig ist – Listen, Zähler oder andere Daten, die sich pro Instanz ändern.
Probier es selbst
-- Erfordert das ShoppingCart-Modul
local ShoppingCart = require('ShoppingCart')
-- Eingaben lesen
local product1 = io.read()
local product2 = io.read()
local product3 = io.read()
local product4 = io.read()
-- TODO: Erstelle zwei Warenkörbe: cartA und cartB
-- TODO: Füge product1 und product2 zu cartA hinzu
-- TODO: Füge product3 und product4 zu cartB hinzu
-- TODO: Drucke "Cart A:" und liste dann die Produkte von cartA auf
-- TODO: Drucke "Cart B:" und liste dann die Produkte von cartB auf
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