如何确保一个table是一个类的对象?

我创建了一个名为 Apple 的类

Apple.lua

function apple_new()

    local self = { }

    local size = 1

    function self.grow()
        size = size + 1
    end

    function self.size()
        return size
    end

    return self
end

我想要定义一个 function(table) ,如果参数 table 最初是由函数 apple_new 创建的,则返回 true 。 我目前还没有找到一种方法来确保'假的苹果'不能在该函数中返回 true

AppleTest.lua

function is_apple(table)
    if type(table) ~= "table" then return false end

    return table.grow ~= nil and table.size ~= nil
end

local x = apple_new()
local y = { size = function() end, grow = function() end }
is_apple(x) -- true
is_apple(y) -- true, 但它是一个假苹果

我相信可以使用元表来解决此问题,并利用__metatable元方法。 但是,如果可能的话,我更喜欢没有使用元表的解决方案。 这相当困难,因为表中的任何变量都可以被复制。

如何实现?

点赞
用户107090
用户107090

Apple.lua 中,添加以下代码:

local Apples = { }
setmetatable(Apples, {__mode = "k"})

function apple_new()
    local self = { }
    Apples[self] = true
    -- 其它操作省略
    return self
end

function is_apple(table)
    return Apples[table] == true
end

为了让苹果对象能被垃圾回收,你需要将 Apples 设置为弱表。

2018-01-28 10:41:18
用户736889
用户736889

如果您想要实现继承和类函数,也可以按照 在 Lua 程序设计中 中的方式进行。

Apple = {}
Apples = {}

function Apple:new (initTable)
    local a = initTable or {}
    table.insert (Apples, a)

    setmetatable (a, self)
    self.__index = self

    return a
end

现在,您为 Apple 定义的任何函数将适用于使用 Apple:new 函数创建的任何对象。所有创建的 Apple 将自动成为 Apples 表的一部分。

2018-01-29 14:55:25