Lua und "Objekte"
» Siedler Map Source Forum » Siedler DEdK Script Forum » Lua und "Objekte"
Seiten: 1
BalistiK
|
#1 05.11.2019 09:48 Beiträge: 70 |
Lua und "Objekte"
Hallo Zusammen,
ich stoße seit letzter Zeit auf ein paar (verständins) Probleme mit Lua. Selbst bin ich behaftet mit der Idee der Objektorientierten Programmierung, welche sich in Lua ansatzweise durch Tables umsetzen lässt.
Vorab eine Frage: Ist es sinnvoll einen "objektorientieren" Lösungsansatz in Lua anzugehen oder sollte man darauf lieber verzichten, sprich sparsam damit umgehen?
Ich stoße da auf folgendes Problem: Ich habe ein Table mit Werten und Funktionen (Klasse). Diesen Table kopiere ich mit samt den Funktionen und !ohne vorgesetzten Werten (Objekt Erzeugung). Hier ein Code-Ausschnitt:
Template = {numbers = {}}; function Template.create(...) local copy = copyTable(Template); for _, v in pairs({unpack(arg)}) do copy:addPlayer(v); end return copy; end function copyTable(origTable) local copy = {}; if type(origTable) == 'table' then for origTableK, origTableV in pairs(origTable) do copy[origTableK] = origTableV; end end return copy; end
Jetzt stoße ich allerding auf folgendes Problem: Der Table wird anscheinend nicht korrekt kopiert und ich weiß nicht warum...
Folgende Aufrufe ergeben die unerwarteten Ergebnisse:
local test1 = Template.create(1, 2); -- "Neues Objekt" for _, v in pairs(test1) do Message(tostring(v)); -- Gibt aus: 1, 2 end local test2 = Template.create(3, 4); -- "Neues Objekt" for _, v in pairs(test2) do Message(tostring(v)); -- Gibt aus: 1, 2, 3, 4 end for _, v in pairs(test1) do Message(tostring(v)); -- Gibt jetzt aus: 1, 2, 3, 4 end
So weit wie ich es überprüfen kann ist test1 ungleich test2, also nicht der selbe Table. Ebenso ist weder test1 noch test2 gleich Template. Wo liegt jetzt genau der Fehler? Ich schätze ich kopiere den Table falsch, aber wie würde ich es richtig machen?
Danke schonmal im Vorraus.
mcb
|
#2 05.11.2019 13:11 Beiträge: 1472 |
Ok, also zur Frage ob OOP in Lua sinnvoll ist: Kommt darauf an, wie viel Script du hast und ob du überhaupt mehrere objekte davon anlegen kannst. Also z.B. für eine eigene KI definitiv ja, Quests und Briefings für ein Mapscript eher nicht und kleinere Funktionen wie CopyTable definitiv nicht.
Und jetzt zur Umsetzung in Lua: Klassischerweise benutzt man dafür metatables, was aber in Siedler nicht ganz so gut funktioniert. Kopieren funktioniert aber genausogut.
Das Problem liegt vermtulich an deinem CopyTable, das keine deep copy macht (ich würde die hier nehmen: https://github.com/mcb5637/s5C...er/comfort/table/CopyTable.lua) und deiner implementierung von Template:addPlayer . Ich vermute du verwendest irgendwo Template anstatt self oder speicherst die Daten in einem table das aus Template referenziert wird.
Edit: Falls du ein beispiel haben willst, wie andere sowas machen sieh dir mal meine Vector imlementierung an: https://github.com/mcb5637/s5C...master/comfort/math/Vector.lua (wobei ich da nicht wirklich Vererbung mache) oder das Script zu twas mapwizard (da ist glaub ich Vererbung bei).
totalwarANGEL
|
#3 06.11.2019 15:45 Beiträge: 2123 |
Versuche es mal mit dieser Funktion zum kopieren (leicht abgeändert):
function CopyTableRecursive(_Source, _Dest) _Dest = _Dest or {}; assert(type(_Source) == "table") assert(type(_Dest) == "table") for k, v in pairs(_Source) do if type(v) == "table" then _Dest[k] = _Dest[k] or {}; for kk, vv in pairs(CopyTableRecursive(v)) do _Dest[k][kk] = _Dest[k][kk] or vv; end else _Dest[k] = _Dest[k] or v; end end return _Dest; end
So verwende ich das selbst erfolgreich in Siedler 5 und 6.
Für Objekte empfiehlt es sich außerdem, wenn man keine Metatables nutzt, eine :New Methode anzulegen. Dazu mein bleibtes Katzen-Beispiel (momentan nur bei mir beliebt):
Cat = {} function Cat:New() local NewCat = CopyTableRecursive(self); NewCat.m_Name = "0815 Katze"; NewCat.m_Gender = 0; NewCat.m_Color = "black"; return NewCat; end function Cat:Name(_Name) if _Name then self.m_Name = _Name; end return self.m_Name; end function Cat:Gender(_Gender) if _Gender then self.m_Gender = _Gender; end return self.m_Gender; end function Cat:Color(_Color) if _Color then self.m_Color = _Color; end return self.m_Color; end -- -------------------------------------------------------------------------- -- Happy = Cat:New(); Happy:Name("Happy"); Happy:Gender(0); Happy:Color("blue"); Carla = Cat:New(); Carla:Name("Carla"); Carla:Gender(1); Carla:Color("white"); Lilly = Cat:New(); Lilly:Name("Lilly"); Lilly:Gender(0); Lilly:Color("black");
In der Art sollte das alles wunderbar klappen.
(Außer ich habe irgend wo einen Tippfehler.)
____________________
Die Welt ist arschlochförmig und wir leben in der Mitte.
Seiten: 1