Lua Logo
Metatables

Wie wir bis jetzt schon wissen sollten, kann man mit tables einige Sachen nicht ohne weiteres machen.
Metatables geben uns aber die Möglichkeit einem Table Anweisungen zu geben, was bei einem ansonsten nicht erlaubten Zugriff auf ein table geschehen soll.
Jedes table oder userdata object in Lua kann ein Metatable haben.

Beispiele für nicht erlaubte Zugriffe:


Wie macht lua das?

Es wird einfach ein table erzeugt, in dem Funktionen liegen, die im Falle einer solchen Handlung aufgerufen werden.

Wird eine Addition mit tables versucht, so sucht lua nach einer Funktion __add in diesem table. Ist diese Funktion vorhanden, so wird sie ausgeführt.

Dazu müssen wir aber das table zunächst machen und dann dem anderen table zuweisen.

Erzeugen des Funktionstables:
    
    metaT={} -- ein Table ist geboren
    metaT.__add = function( table1, table2 )
                    -- jetzt kommen hier alle Anweisungen hinein,
                    -- die im Falle einer Addition von tables
                    -- durchgeführt werden sollen.
                end
    
Natürlich können wir auch gleichzeitig für andere Handlungen eine Funktion zuweisen:
    
    metaT.__sub = function( table1, table2 )
                    -- jetzt kommen hier alle Anweisungen hinein,
                    -- die im Falle einer Subtraktition von tables
                    -- durchgeführt werden sollen.
                end
    metaT.__mul = function( table1, table2 )
                    -- jetzt kommen hier alle Anweisungen hinein,
                    -- die im Falle einer Multiplikation von tables
                    -- durchgeführt werden sollen.
                end
    
und so weiter. Die Liste der Möglichkeiten ist umfangreich. Wichtig ist zunächst zu wissen, wie man eine Funktion für eine bestimmte Handlung erstellt.

jetzt müssen wir noch dem table das Metatable zuweisen.

Dies geschieht einfach mit:
    
    setmetatable(meinTable, metaT)
    
Was in den Funktionen steht, ist vollkommen uns überlassen. Wichtig ist nur der Rückgabewert.
Nehmen wir einmal an, wir wollen zu einer Position in X-Richtung 100 addieren und in Y-Richtung 500
    
    pos  = { X = 1205, Y = 5241 }
    diff = { X = 100,  Y =  500 } -- unsere Differenz
    
Würden wir jetzt schreiben:
    
    ergebnis = pos + diff 
    
Dann hätten wir einen dicken Fehler.(attempt to perform arithmetic on global `pos' (a table value) )

Machen wir also ein Metatable
    
    metaT={} -- ein Table ist geboren
    metaT.__add = function( table1, table2 )
                    local table3 = {}
                    table3.X = table1.X + table2.X 
                    table3.Y = table1.Y + table2.Y
                    return table3
                end
    setmetatable(pos, metaT)
    ergebnis = pos + diff 
    
Das geht natürlich wesendlich einfacher ist aber nicht so übersichtlich:
    
    metaT={} -- ein Table ist geboren
    metaT.__add = function( table1, table2 )
                    return {X = table1.X + table2.X, Y = table1.Y + table2.Y }
                end
    setmetatable(pos, metaT)
    ergebnis = pos + diff 
    
Dann lassen wir uns das Ergebnis ausdrucken:





Das ganze geht auch anders herum: ergebnis = diff + pos 
Für diff können wir auch alles mögliche einsetzten (Zahlen, Strings,...). Die Funktion muss das nur verkraften können.

Funktion Anwendungsfall (wird aufgerufen wenn:)
__add Addition
__sub Subtraktion
__mul Multiplication
__div Division
__pow Potenzierung
__unm Wenn ein table mit dem unären Operator - versehen wird
__concat Wenn zwei tables mit .. verknüpft werden
__eq zwei tables werden mit == verglichen
__it zwei tables werden mit < verglichen
__le zwei tables werden mit <= verglichen
__index Es wurde ein Wert aufgerufen, den es in dem table nicht gibt.
__newindex Wenn ein table ein neues Element bekommt. Z.B x und y sind vorhanden, z wird definiert.
__call Wenn irgendein Wert im table angesprochen wird
__mode
__metatable
__tostring Wenn die Funktion tostring auf ein table angewendet wird
__gc
nach obenNoch lange nicht fertig.
Die Vervielfältigung der auf diesen Seiten enthaltenen Informationen und Grafiken ist untersagt, ausgenommen davon ist sämtlicher auf diesen Seiten angezeigter Quellcode.
Siehe auch: Haftungsausschluss
Copyright © Robert Schmitz 2006