Gemeinsam vs. Einzigartig
Teil des Abschnitts Object Oriented Programming der Lua-Journey von Coddy — Lektion 35 von 70.
Bei der Arbeit mit Vererbung ist es wichtig zu verstehen, wo die einzelnen Daten liegen. Einige Attribute werden geteilt – in der Elternklasse definiert und für alle Kindklassen zugänglich. Andere sind einzigartig – speziell in der Kindklasse oder Instanz erstellt.
Betrachten Sie diese Hierarchie:
local Animal = {}
Animal.__index = Animal
Animal.kingdom = "Animalia" -- Gemeinsam genutzt: auf der Klasse definiert
function Animal:new(name)
local obj = {name = name} -- Einzigartig: auf jeder Instanz gespeichert
setmetatable(obj, Animal)
return obj
endlocal Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
Dog.sound = "bark" -- Wird von allen Dogs geteilt
function Dog:new(name, breed)
local obj = Animal.new(Animal, name)
obj.breed = breed -- Einzigartig: jeder Dog hat seine eigene Rasse
setmetatable(obj, Dog)
return obj
endWenn Sie eine Dog-Instanz erstellen, existieren einige Werte direkt auf dem Objekt, während andere über die Lookup-Kette gefunden werden:
local rex = Dog:new("Rex", "German Shepherd")
-- Einzigartig für diese Instanz (gespeichert auf rex)
print(rex.name) -- "Rex"
print(rex.breed) -- "German Shepherd"-- Geteilt (über Lookup gefunden)
print(rex.sound) -- "bark" (von Dog)
print(rex.kingdom) -- "Animalia" (von Animal)Der entscheidende Unterschied: Felder, die obj in Konstruktoren zugewiesen werden, sind für jede Instanz eindeutig, während Felder, die direkt in Klassentabellen definiert sind, von allen Instanzen dieser Klasse und deren Unterklassen gemeinsam genutzt werden.
Aufgabe
EinfachLassen Sie uns untersuchen, wie Daten durch eine Vererbungshierarchie fließen, indem wir ein Klassensystem aus Creature und Dragon aufbauen. Sie werden aus erster Hand sehen, welche Attribute von allen Instanzen gemeinsam genutzt werden und welche für jedes einzelne Objekt eindeutig sind.
Sie werden Ihren Code auf drei Dateien verteilen:
Creature.lua: Definieren Sie Ihre Elternklasse mit einem gemeinsamen Attribut auf Klassenebeneworld = "Fantasy Realm", das alle Kreaturen teilen. Fügen Sie einen:new(name)-Konstruktor hinzu, der den Namen der Kreatur als Instanzattribut speichert.Dragon.lua: Definieren Sie Ihre Kindklasse, die von Creature erbt. Fügen Sie ein gemeinsames Attribut auf Klassenebeneelement = "fire"hinzu, das alle Drachen teilen. Ihr:new(name, color)-Konstruktor sollte den Eltern-Konstruktor für den Namen aufrufen und danncolorals eindeutiges Instanzattribut für jeden Drachen hinzufügen.main.lua: Erstellen Sie zwei verschiedene Drachen und inspizieren Sie deren Attribute, um den Unterschied zwischen gemeinsamen und eindeutigen Daten zu demonstrieren.
Sie erhalten zwei Eingaben:
- Den Namen und die Farbe des ersten Drachen, getrennt durch ein Komma (z. B.
Smaug,red) - Den Namen und die Farbe des zweiten Drachen, getrennt durch ein Komma (z. B.
Draco,gold)
Erstellen Sie in Ihrer Hauptdatei beide Drachen mit ihren jeweiligen Namen und Farben. Geben Sie dann die folgenden Informationen in genau dieser Reihenfolge aus:
namedes ersten Drachencolordes ersten Drachennamedes zweiten Drachencolordes zweiten Drachenelementdes ersten Drachen (gemeinsam genutzt von der Dragon-Klasse)elementdes zweiten Drachen (gemeinsam genutzt von der Dragon-Klasse)worlddes ersten Drachen (gemeinsam genutzt von der Creature-Klasse)
Wenn die Eingaben beispielsweise Smaug,red und Draco,gold sind, sollte die Ausgabe wie folgt aussehen:
Smaug
red
Draco
gold
fire
fire
Fantasy RealmBeachten Sie, dass name und color für jeden Drachen unterschiedlich sind (eindeutige Instanzattribute), während element und world für beide gleich sind (gemeinsame Klassenattribute, die über die Lookup-Kette gefunden werden).
Spickzettel
In Vererbungshierarchien können Attribute entweder gemeinsam genutzt (auf der Klassentabelle definiert) oder einzigartig (auf einzelnen Instanzen gespeichert) sein.
Gemeinsam genutzte Attribute werden direkt in Klassentabellen definiert und über die Metatabellen-Suchkette aufgerufen:
local Animal = {}
Animal.__index = Animal
Animal.kingdom = "Animalia" -- Gemeinsam für alle AnimalsEinzigartige Attribute werden dem Instanzobjekt (obj) in Konstruktoren zugewiesen:
function Animal:new(name)
local obj = {name = name} -- Einzigartig für jede Instanz
setmetatable(obj, Animal)
return obj
endUnterklassen können ihre eigenen gemeinsam genutzten Attribute haben, während sie Attribute der Elternklasse erben:
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
Dog.sound = "bark" -- Gemeinsam für alle Dogs
function Dog:new(name, breed)
local obj = Animal.new(Animal, name) -- Eltern-Konstruktor aufrufen
obj.breed = breed -- Einzigartiges Attribut der Unterklasse hinzufügen
setmetatable(obj, Dog)
return obj
endZugriff auf Attribute:
local rex = Dog:new("Rex", "German Shepherd")
-- Einzigartig (direkt auf rex gespeichert)
print(rex.name) -- "Rex"
print(rex.breed) -- "German Shepherd"
-- Gemeinsam genutzt (über Metatabellen-Suche gefunden)
print(rex.sound) -- "bark" (von der Dog-Klasse)
print(rex.kingdom) -- "Animalia" (von der Animal-Klasse)Probier es selbst
-- main.lua: Drachen erstellen und gemeinsame vs. eindeutige Attribute demonstrieren
local Dragon = require('Dragon')
-- Eingabe für den ersten Drachen lesen (Name, Farbe)
local input1 = io.read()
-- Eingabe für den zweiten Drachen lesen (Name, Farbe)
local input2 = io.read()
-- TODO: Die erste Eingabe parsen, um Name und Farbe zu extrahieren
-- Hinweis: string.match mit dem Muster "([^,]+),([^,]+)" verwenden
-- TODO: Die zweite Eingabe parsen, um Name und Farbe zu extrahieren
-- TODO: Den ersten Drachen mit seinem Namen und seiner Farbe erstellen
-- TODO: Den zweiten Drachen mit seinem Namen und seiner Farbe erstellen
-- TODO: Folgendes in dieser Reihenfolge ausgeben:
-- 1. Name des ersten Drachens
-- 2. Farbe des ersten Drachens
-- 3. Name des zweiten Drachens
-- 4. Farbe des zweiten Drachens
-- 5. Element des ersten Drachens (von der Dragon-Klasse geteilt)
-- 6. Element des zweiten Drachens (von der Dragon-Klasse geteilt)
-- 7. Welt des ersten Drachens (von der Creature-Klasse geteilt)
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