[Tutorial] Globale und lokale Variablen

  • [Tutorial] Globale und lokale Variablen

    (Ich entschuldige mich im Vorraus fuer die schlechte Formatierung des Quellcodes.)

    Guten Tag,

    da man immer wieder leicht sehen kann, dass manche Leute ohne konkrete Kompetenzen im Bereich der Variablen in LUA / MTA stets Fehler machen und korrekte Aussagen bestreiten,
    habe ich mir die Zeit genommen ein kleines Tutorial zum Thema globale und lokale Variablen zu schreiben.

    Einleitung
    (Fuer die Richtigkeit dieses Tutorials und dessen Angaben uebernehme ich keine Haftung.)

    Es gibt in LUA viele Arten von Variablen. Dazu gehoeren unter anderen globale Variablen und lokale Variablen.
    Wir ignorieren nun mal den Fakt, dass jede Variable einen gewissen Datentypen besitzt. In Lua wird der Datentyp intern (und ein wenig extern) behandelt.

    Was genau eine Variable ist habt ihr alle in der Schule gelernt. Deshalb werde ich dieses Thema auch ueberspringen.

    Initialisierung & Deklaration
    Die oben genannten Woerter spielen in Lua nicht so eine grosse Rolle, wie in anderen Programmiersprachen.
    Jedoch sollte man auch den Unterschied zwischen den beiden Woertern kennen, weshalb ich diesen kurz Ansprechen werde.

    Deklaration
    Unter Deklaration versteht man das Bekanntmachen von Variablen.
    Variablen werden Deklariert und in etwa "Vorbereitet".
    In anderen Programmiersprachen koennte man das so schreiben:

    (Java:)

    Lua
    int foo;

    Die Bekanntmachung wird in Lua nur mit dem "local" Keyword sinnvoll.

    Initialisierung
    Bei der Initialisierung wird der Variable einen Wert zugewiesen. In Lua sieht das in etwa so aus:

    (Lua:)

    Lua
    foo = 5;

    Selbstverstaendlich kann man auch eine Variable deklarieren und gleichzeitig initalisieren.

    (Java:)

    Lua
    int foo = 5;


    Globale Variablen
    Eine globale Variable ist eine Variable, welche Ihr von jeder Stelle eures Scriptes aus verwenden und erreichen koennt.

    Beispiel von globalen Variablen:

    server/script.lua:

    Lua
    bar = "bar";
    foo = bar;

    Die Variablen "bar" und "foo" sind im kompletten Script erreichbar.
    Das veraendern dieser Variablen hat zufolge, dass diese Variable im kompletten Script geaendert wird.

    Lokale Variablen
    Eine Lokale Variable ist eine Variable, welche nur in einem gewissen Bereich (Block) existieren.
    Sie wird mit dem Prefix 'local' deklariert.
    Solltet Ihr eine lokale Variable in der ersten Zeile eures Scriptes schreiben

    Lua
    local x = 5;

    So ist diese Variable nur in dieser Datei vorhanden.
    Der Gueltigkeitsbereich dieser Variable limiert sich also nur auf diese Datei.

    Solltet Ihr eine Variable in einer Funktion deklarieren, so ist der Gueltigkeitsbereich der Variable nur auf diese Funktion limitiert.

    Lua
    function foo()			-- Deklarierung und Initialisierung einer globalen Funktion
    	local bar = 5;		-- Deklarierung und Initialisierung einer lokalen Variable
    
    	print(bar);			-- Ausgabe: 5
    end
    
    
    print(bar);				-- Ausgabe: nil;

    Solltet Ihr diese Variable ohne den 'local' Prefix erstellt habe, so streckt sich der Gueltigkeitsbereich der Variable automatisch auf das Gesammte Script aus.

    Lua
    function foo()			-- Deklarierung und Initialisierung einer globalen Funktion
    	bar = 5;			-- Deklarierung und Initialisierung einer Globalen Variable
    
    	print(bar);			-- Ausgabe: 5
    end
    
    
    print(bar);				-- Ausgabe: 5;

    Falls Ihr diese Variable trotzdem im gesammten Script verwenden moechtet, koennt Ihr diese Variable deklarieren und in einer Funktion initialisieren. So bleibt der Gueltigkeitsbereich
    der Variable auf diese Datei beschraenkt, kann jedoch modifiziert und zugaenglich sein.

    Wichtig ist zu sagen, dass in Lua JEDE Variable lokal gesetzt werden kann. Es gibt keine Variable, welche nicht Lokal sein kann.

    Wie schon angemerkt kann man auch Funktionen lokal setzen. Solltet Ihr eine Funktion so definieren:


    Lua
    function foo()
    	return "bar"
    end

    So wird die Funktion "foo" Global erstellt und ist im kompletten Script erreichbar.
    Ausserdem kann folgende Situation gegeben sein:

    Lua
    function joinHandler()	-- Globale funktion
    
    
    end
    
    
    addEventHandler("onPlayerJoin", getRootElement(), joinHandler)

    In diesem Beispiel wurde die Funktion joinHandler Global erstellt, welche jedoch nur von dem Event "onPlayerJoin" benutzt wird.
    Diese Funktion Global zu stellen ist somit kompletter Bullshit, da sie von keinem anderen Teil des Scriptes benutzt wird oder werden sollte.
    Im schlimmsten Fall kann es sogar sein, dass diese Funktion in der Laufzeit von einer anderen Funktion ueberschrieben wird.

    Dies kann man verhindern, indem man die Funktion von Anfang an schon lokal deklariert.

    Somit kann man schonmal das Schlimmste Verhindern.
    Dieses Beispiel beschraenkt sich uebrigends nicht nur auf Funktionen.

    Nehmen wir ein Beispiel an der Variable Houses.
    'Houses' ist eine Tabelle welche saemtliche Informationen, Elemente und Daten zu jeden Haeusern auf dem Server enthaelt.

    Die Variable Houses ist Global und kann von jedem Standort des Gamemodes erreicht werden.
    Nehmen wir mal das Schlimmste vom Schlimmsten an und sagen, dass diese Variable ungefaehr 2000 Haeuser besitzt.
    In dieser Variable befinden sich Event-Handler, Pickup-Elemente, Funktionen, Methoden, Attribute und MySQL Speicherbefehle.
    (Instanzen von Haeusern zum Beispiel)

    In einer Funktion schreibt Hans Peter folgendes:

    Schreibt Hans Peter nun die Variable 'Houses' ohne den 'lokal' Prefix:

    Hat er die gesammte Haustabelle des Servers ueberschrieben.
    Die Haeuser koennen somit nie wieder in der Laufzeit erreicht werden.
    Was folgen wird sind Fehler, welche dafuer sorgen werden dass Wahrscheinlich das Gesammte Gamemode neugestartet werden muss.
    Dieses Problem existiert meist nur in Lua weshalb man hier besonderst auf diesen Fehler achten sollte und ihn niemals unterschaetzen sollte.
    In anderen Programmiersprachen existiert hierfuer das Schluesselwort "Protected". So kann eine Ueberschreibung verhindert werden.

    Dieses Problem kann man in Lua jedoch verhindern, indem man eine Managerklasse fuer die Haeser schreibt.

    Die Managerklasse enthaelt eine Klassenvariable welche die Daten der Haeuser sicher speichert. Da die Klasse mit einem getInstance() aufgerufen wird, ist eine Ueberschreibung sehr gut zu verhindern.
    (Selbstverstaendlich kann man diese Variable auch ueberschreiben, aber an sowas denkt man und macht es nicht aus versehen.)


    Die Globale Umgebung von Lua (_G)
    Die Globale Umgebung von Lua wird auch die _G Variable genannt.


    Lua
    _G

    In dieser Variable befinden sich alle globalen Variablen.
    Wie man genau diese Umgebung benutzen kann, moechte ich ungerne Ansprechen da es fuer die meisten hier eventuell zu Komplex sein wird.
    (Stichwort setfenv)

    Diese Umgebung wird von MTA zur Speicherung der globalen Variablen verwendet.
    Sie sieht schoen aus, ist Blau und sollte man sicherlich benutzen. Richtig? Falsch!

    Globale Variablen in der Umbebung sind beispielsweise Funktionen wie "getPlayerName" oder "getElementData", aber auch Variablen wie "root" oder "localPlayer".

    Ich kann nicht mehr als Betonen, wie sehr man die Finger von dieser Umgebung lassen sollte. Diese Umbebung wird intern von
    MTA stets verwendet und man sollte niemals, nie und nimmer irgendwelche sinnlosen Variablen in dieser Globalen Umgebung speichern.

    Es gibt viele Personen, welche so ziemlich jede Elemente die sie erstellen in dieser Umgebung einspeichern.
    Entweder haben diese Personen nicht mehr alle Tassen im Schrank oder sie folgen ein Scriptingstyle einer diversen Person,
    welche vor 6 Jahren kein blassen Schimmer von dem hatte, was sie eigentlich tat.
    Der Grund dieser Person war schlichtweg unwissenheit.

    Im schlimmsten Fall kann das Script nicht mehr laufen, man ueberschreibt wichtige Variablen oder es laeuft sehr langsam, da die Umgebung zu Zugestopft ist.
    Fakt: Diese Variable ist nicht zur Speicherung von Gamemodedaten oder Elementen vorhanden, sondern hat einen eigenen Zweck.

    Zur Not kann man stets eine eigene Umbebung erstellen: (Am besten mit einer Managerklasse)

    Lua
    Umgebung_				 	= {}
    
    
    Umgebung_.foo				= "bar";
    Umgebung_["Fahrzeug_5"] 	= Vehicle(...);

    Aber bitte nicht in der _G Umgebung.
    In der Methode oben enthaelt die _G Umgebung automatisch die 2. Umbebung. Solltet ihr die _G Umgebung manipulieren, manipuliert ihr auch die 2. Umgebung.
    Nur weil eine Variable blau markiert wird, heisst es nicht dass sie automatisch die beste und Performanteste Moeglichkeit ist.


    Da dieses Missverstaendnis abschliessend erklaert wurde, moechte ich mich bei all denen Bedanken, die dieses Tutorial durchgelesen haben.

    Sollten Fehler, Unwissenheit, oder falsche Angaben angegeben wurden sein, so bitte ich euch eure Meinung und Fehler zu berichten.
    Ich werde anschliessend den Fehler beheben.

    Falls noch Fragen offen sind, koennen diese auch gerne gefragt werden.

    Mit freundlichen Grüßen
    Noneatme

    Mit freundlichen Grüßen

    Einmal editiert, zuletzt von Noneatme (7. April 2015 um 13:40)

  • Dieses Thema enthält 3 weitere Beiträge, die nur für registrierte Benutzer sichtbar sind, bitte registrieren Sie sich oder melden Sie sich an um diese lesen zu können.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!