Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lua check if a table is an 'instance'

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
like image 682
aoiee Avatar asked Jul 19 '17 14:07

aoiee


People also ask

How do you check if an element is in a table Lua?

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'.

How can you tell if a Lua table is empty?

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.

What are metatables used for Lua?

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.

Is there classes in Lua?

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.


2 Answers

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))
like image 159
moteus Avatar answered Oct 23 '22 22:10

moteus


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.

like image 3
Vlad Avatar answered Oct 23 '22 22:10

Vlad