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
The simple way of handling the issue that you have is to make another table, of value to key. ie. you have 2 tables that have the same value, one pointing one direction, one pointing the other. You can then query the new table to see if it has the key 'element'.
One possibility would be to count the number of elements, by using the metatable "newindex" key. When assigning something not nil , increment the counter (the counter could live in the metatable as well) and when assigning nil , decrement the counter. Testing for empty table would be to test the counter with 0.
Metatables allow us to change the behavior of a table. For instance, using metatables, we can define how Lua computes the expression a+b , where a and b are tables. Whenever Lua tries to add two tables, it checks whether either of them has a metatable and whether that metatable has an __add field.
Lua does not have the concept of class; each object defines its own behavior and has a shape of its own. Nevertheless, it is not difficult to emulate classes in Lua, following the lead from prototype-based languages, such as Self and NewtonScript. In those languages, objects have no classes.
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))
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With