lua-users home
lua-l archive

Re: Metatables are "hard" (Re: Question about __index and classes)

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Sunday 11, Daurnimator wrote:
> On 12 September 2011 00:26, Richter, Jörg <Joerg.Richter@pdv-fs.de> wrote:
> >> In Lua you cannot sandbox a metatable away. An offending script still
> >> might just call getmetatable.
> > 
> > Then use __metatable:
> > 
> > http://www.lua.org/manual/5.1/manual.html#pdf-getmetatable
> > 
> > Jörg
> 
> As a note to using __metatable; its a good idea to return a
> string/object unique to each metatable.
> Its nice if code can use getmetatable() to check for type equality.
Here is one method for type checking that I have used, that also allows hiding 
the metatable.
-- unique type key, not visible outside the object's implementation.
local object_key = {}
local mt = {
 __metatable = false, -- hide metatable
}
-- Don't use metatable as __index, this would allow object_key to leak
-- to outside code.
-- -- mt[object_key] = mt
-- -- mt.__index = mt
-- code could call "pairs(obj.__index)" to find object_key.
-- if __index a different table
mt.__index = {
 [object_key] = mt,
-- methods go here.
}
-- or if __index is a function
function mt.__index(obj, key)
 -- put your normal __index function code here.
 -- last check for object_key lookup
 if key == object_key then return mt end
 return nil -- key not found, maybe assert here about missing object method?
end
-- this type checking method could be made public.
function check_object_type(obj)
 return (obj[object_key] == mt)
end
function new_object(init)
 if init and check_object_type(init) then
 -- init is already the correct type, Copy it?
 return init -- just return it as-is
 end
 return setmetatable(init or {}, mt)
end
With this method no code outside the object's implementation can get the 
object's type tag "object_key" or metatable and make a fake object.
-- 
Robert G. Jakabosky

AltStyle によって変換されたページ (->オリジナル) /