Reputation: 355
Given a table, is there a way to check if it is an instance object of any class?
Assume all class definition looks like:
Class = {}
Class.__index = Class
function Class.new()
return setmetatable({}, Class) -- returns an instance
end
Upvotes: 7
Views: 4096
Reputation: 2235
I use just getmetatable function
if getmetatable(thing) == Class then
But if you use some type of inheritence then you can try this one
local A = {} A.__index = A
function A:new() return setmetatable({}, A) end
function A:foo() print('foo') end
local B = setmetatable({}, A) B.__index = B
function B:new() return setmetatable({}, B) end
function B:boo() print("boo") end
local function is_instance(o, class)
while o do
o = getmetatable(o)
if class == o then return true end
end
return false
end
local a = A:new()
local b = B:new()
a:foo()
b:foo()
b:boo()
print(is_instance(a, A))
print(is_instance(a, B))
print(is_instance(b, B))
print(is_instance(b, A))
Upvotes: 6
Reputation: 5847
In theory you could read table's metatable with getmetatable()
, and compare received table agains list of classes known to you.
But it means metatable shouldn't be protected (__metatable
field is not set to something different, getmetatable()
is not removed within sandbox, etc), and you should know all available classes.
If there some metatable set on a table, it doesn't mean that table is a part of class hierarchy, or class at all. It just might use metatables to solve its own tasks.
Upvotes: 3