2016-09-09 2 views
1

Je veux « décrochez » un métatable d'une table et je me demandais si:Retrait métatables d'une table dans Lua

tbl = setmetatable(tbl, false) -- or nil 

est la bonne façon de le faire? Je n'ai pas trouvé d'informations sur la façon de le faire correctement. Dois-je utiliser un opérateur d'affectation?

Aussi, serait-ce suffisant pour détruire le métatable fixé à la table si le métatable n'a jamais eu une référence et a été anonyme ?:

tbl = setmetatable({}, {__index = something}) 
-- later on: 
tbl = nil 

et le collecteur des ordures serait suffisant pour enlever les deux tableaux?

+2

Rien ne devrait aller, il n'acceptera pas faux. –

+2

http://www.lua.org/manual/5.3/manual.html, https://www.lua.org/cgi-bin/demo – Piglet

Répondre

5

Selon la référence Lua, que vous devriez toujours consulter avant de poser une question, setmetatable(tbl, nil) supprimera la métatable de la table tbl à moins que la métatable originale de tbl ne soit protégée. Ou disons mieux qu'il ne supprime pas la métatable mais la référence à celle-ci. La table qui a servi de table de conversion ne sera bien sûr pas supprimée tant qu'il y aura d'autres références.

Avant de demander aux gens si un simple appel de fonction fonctionne, essayez-le vous-même. Vous pouvez utiliser https://www.lua.org/cgi-bin/demo ou n'importe quel autre interprète Lua et vous obtenez votre réponse en quelques secondes sans que personne d'autre ne soit impliqué.

L'exécution de ce code:

setmetatable({}, false) 

ou

setmetatable({}) 

se traduira par

entrée: 1: mauvais Argument n ° 2 à 'SetMetaTable' (nul ou tableau prévu)

Maintenant, vous savez que vous ne pouvez pas entrer faux et vous devez entrer nil explicitement.

à la caisse cette chose __metatable vous avez lu dans le manuel de référence que vous pourriez essayer ce code

local tbl = setmetatable({}, {__metatable = true}) 
setmetatable(tbl, nil) 

qui se traduit par la sortie suivante:

entrée

: 2: ne peut pas changer protégé métatable

Pour la deuxième partie de votre question:

tbl = nil ne supprimera pas la table référencée par tbl. Cela ne fera que supprimer la référence tbl.

local a = {} 
local b = a 
b = nil 
print(a) 

a est toujours une table. Vous avez seulement supprimé l'une de ses références.

Une fois qu'il n'y a plus de référence, le garbage collector peut récupérer la table.

setmetatable(tbl, {}) va établir une référence à la table retournée par le constructeur de la table {} et stocker cette référence quelque part dans les entrailles de tbl.

Si tbl était la dernière référence à cette table, elle sera collectée comme une poubelle à un moment donné. Ensuite, bien sûr, la seule référence à la table que vous définissez comme métatable sera également supprimée et elle sera également supprimée.

Si vous faites quelque chose comme ça:

local a = {} 
local b = setmetatable({}, a) 

, a = nil ne supprimera pas b de métatable

Alors oui, il supprimera les deux tables si aucune autre référence à l'un d'entre eux reste.

+1

Il convient de souligner que si le développeur a protégé la métatable en réglant ' __metable', vous pouvez toujours y accéder * si * 'debug.getmetatable' existe (ou si vous êtes capable de charger vous-même dans la librairie de débogage) - Sinon, vous devrez le faire via l'API C – Olipro