Lua 如何检查一个表是否为“实例对象”

给定一个表,有没有办法检查它是否是任何类的实例对象?

假设所有的类定义都像这样:

Class = {}
Class.__index = Class

function Class.new()
    return setmetatable({}, Class) -- 返回一个实例对象
end
点赞
用户5675002
用户5675002

在理论上,您可以使用getmetatable()读取表的元表,并将接收的表与您所知道的类列表进行比较。

但这意味着元表不应受保护(__metatable字段未设置为不同的内容,getmetatable()未在沙盒中删除等),并且您应该知道所有可用的类。

如果某个表上设置了元表,并不意味着表是类层次结构的一部分,或者根本不是类。 它可能仅使用元表来解决自己的任务。

2017-07-19 14:10:59
用户2328287
用户2328287

我只使用了 getmetatable 函数:

if getmetatable(thing) == Class then

但如果你使用了某种继承类型,你可以尝试下面这个:

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))
2017-07-19 14:11:14