Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 确保表是类的对象?_Oop_Lua - Fatal编程技术网

Oop 确保表是类的对象?

Oop 确保表是类的对象?,oop,lua,Oop,Lua,我制作了一个类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 如果参数table最初是由函数apple\u new创建的

我制作了一个类
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
如果参数
table
最初是由函数
apple\u new
创建的,我想定义一个
函数(table)
,它返回
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, but it's a fake apple
我相信一个解决方案存在于元表中,它利用了
\uuu元表
元方法。但是,如果可能的话,我更喜欢没有它们的解决方案。这相当困难,因为表中的任何变量都可以复制


如何做到这一点?

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
设置为弱表。

如果您想实现继承和类函数,也可以按照中的方式来实现


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

我不知道弱表是可能的。谢谢@lhf-OP的函数
is_apple
apple\u new
在不同的文件中定义。如果是这样的话:
localy={size=function()end,grow=function()end}Apples[y]=true
我在那篇文章中使用了。它看起来更漂亮,执行速度更快,但只会损失一点内存。它还绕过了
语法。我不太喜欢使用元表作为类的证明,因为
getmetatable
方法如果用户有权访问它,就会造成严重破坏。您可以通过
\uuu metaletable
隐藏元表,但这样会阻止以后扩展类。如果使用setmetatable方法,您可以将对象实例上的构造函数与类对象进行比较:local a=Apple:new({foo='bar;})local isAnApple=(a.new=Apple.new)--true
Apple = {}
Apples = {}

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

    setmetatable (a, self)
    self.__index = self

    return a
end