- Offizieller Beitrag
MTA Class Library
Einige kennen meine Class Library ja bereits, den anderen möchte ich sie kurz vorstellen.
Kurz zur Geschichte der Class Library:
Nachdem ich die Grundlagen der Objektorientierten Programmierung in Lua verstanden hatte, wollte ich dies auch auf Elemente anwenden können. Nach einer Menge rumprobiererei bin ich dann auf die Lösung gekommen und mit der Zeit sind immer mehr Features dazugekommen. Prinzipiell enthält die Class Library viele Funktionen um OOP mit Lua und MTA einfacher zu machen.
Was ist möglich?
Eigentlich sind alle relevanten Funktionen im Code dokumentiert, hier also erstmal ein kleiner Überblick mit Beispielen, was mit der Class Library möglich ist.
Per-Element Storage
Klassen für Elemente
Spoiler anzeigen
Elementtypklassen
Spoiler anzeigen
Häufig benötigt man nur eine Klasse für einen Elementtyp. Ein gutes Beispiel dafür ist eine Spielerklasse. Damit man sich das enew bei onPlayerConnect sparen kann, gibt es registerElementClass(elementTyp, klasse).
PlayerClass = {}
function PlayerClass:hallo()
outputChatBox("Hallo! Ich bin "..self:getName(), root)
end
function PlayerClass:getName()
return getPlayerName(self)
end
registerElementClass("player", PlayerClass)
local player = getRandomPlayer()
player:hallo() -- output: "Hallo! Ich bin [name]"
Alles anzeigen
Vereinfachung von "normaler" (tablebasierter OOP) durch new und delete
Spoiler anzeigen
Die Funktionen new und delete sind ähnlich ihrem C++ Equivalent. new(Klasse, Argument1, Argument2...) erzeugt eine neue Instanz der Klasse und ruft die Klassenfunktion Klasse:constructor mit den übergebenen Parametern auf. Weiterhin ruft new alle "derived_constructor"-Funktionen in Klassen auf, von denen die Klasse erbt.
delete(Instanz/Element) ruft derzeit nur die Klassenfunktion Klasse:destructor mit den übergebenen Parametern auf. Ein "derived_destructor" ist derzeit nicht implementiert, aber ist geplant. Ein derived_destructor ist ähnlich wie der derived_constructor ebenfalls verfügbar.
Mehrfachvererbung und Polymorphie
Spoiler anzeigen
Die Funktion inherit(from[, what = {}]) ermöglicht simple Vererbung.
Basisklasse = {}
function Basisklasse:test()
print("hallo")
end
function Basisklasse:testZwei()
print("hallo zwei")
end
Klasse = inherit(Basisklasse, {}) -- {} könnte hier weggelassen werden
function Klasse:test()
print("Abgeleitete Klasse")
end
local instance = new(Klasse)
instance:test() -- "Abgeleitete Klasse"
instance:testZwei() -- "hallo zwei"
Alles anzeigen
Analog ist auch Mehrfachvererbung möglich, indem mehrmals inherit angewendet wird.
BasisklasseA = {}
function BasisklasseA:FuncA()
print("BasisklasseA")
end
BasisklasseB = {}
function BasisklasseB:FuncB()
print("BasisklasseB")
end
Klasse = {}
inherit(BasisklasseA, Klasse)
inherit(BasisklasseB, Klasse)
local instance = new(Klasse)
instance:FuncA() -- "BasisklasseA"
instance:FuncB() -- "BasisklasseB"
Alles anzeigen
Zusätzliche Hilfsfunktionen für Vererbung
Spoiler anzeigen
Zusätzlich gibt es folgende Funktionen zur Hilfe bei der Handhabung von Vererbungen
table super(instance/class)
Gibt eine Table der Basisklassen zurück, von denen die Klasse erbt. Wird eine Instanz übergeben, so wird die Klasse der Instanz zurückgegeben.
bool instanceof(instance, class, direct = false)
Gibt zurück, ob instance von class erbt (bzw. eine Instanz von class ist). Ist direct = true, dann wird nur geprüft ob instance direkt und ohne weitere Vererbung von class erbt.
Changehandler für Tables
Spoiler anzeigen
Hinter der Funktion addChangeHandler(instance, key, func) verbirgt sich eine extrem nützliche Funktion, die es euch ermöglicht eine Funktion auszuführen, wenn sich ein Wert in einer Table ändert.
Wollt ihr beispielsweise, dass sobald sich der "score" Wert einer table ändert, dieser in der MySQL Datenbank gesichert wird, so ist dies folgendermaßen möglich:
function broadcastScore(self, newvalue)
outputChatBox("Der Score ist jetzt "..tostring(newvalue))
end
local tab = {}
addChangeHandler(tab, "score", broadcastScore)
tab.score = 12 -- "Der Score ist jetzt 12"
Gibt der Changehandler etwas anderes, als "nil" zurück, so wird der Wert auf den Rückgabewert geändert. Dadurch lässt sich beispielsweise ein Key als Read-Only festlegen:
Lizenz
Die Class Library steht unter der MIT/X11 Lizenz. Die sollte genug Freiheiten für jeden einräumen.
Lizenztext
Copyright (c) 2013 MrX / sbx320
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Besonderen Dank
- Jusonex für das Finden von vielen Bugs im laufe der Entwicklungszeit
- Krischkros für das Im-voraus-lesen dieses Threads
Download
Download (Direktlink): classlib.lua
Github Repository: https://github.com/sbx320/lua_utils
Bugs, Featurewünsche und Patches bitte entweder direkt hier im Thread oder via PN oder Skype.
Fragen am besten hier in den Thread, dann haben die anderen auch etwas davon.