我正在研究 lua 中的元表,现在我有这样一个任务:有一个t带有字段pos和的表size,它们分别是两个数字的数组 -[x, y]和[width, height]。实际上,没有t.x/ ,但我想实现某种语法糖,以便/t.y可以访问表。这是我的做法:t.xt.y
local t = {
pos = {2, 4},
size = {8, 16}
}
setmetatable(t, {
__index = function(table, key)
if key == "x" then return table.pos[1]
elseif key == "y" then return table.pos[2]
elseif key == "w" then return table.size[1]
elseif key == "h" then return table.size[2]
end
end,
__newindex = function(table, key, value)
if key == "x" then table.pos[1] = value
elseif key == "y" then table.pos[2] = value
elseif key == "w" then table.size[1] = value
elseif key == "h" then table.size[2] = value
end
end
})
print(t.x) -- 2
t.x = 222
print(t.pos[1]) -- 222
...一切都很好!我对上面的代码没有任何问题,但是当我尝试使用 OOP 在我的代码中实现这个方案时,问题就开始了。如您所知,lua 中没有开箱即用的 OOP,但有一些方法可以使用元方法自己实现。为了不重复造轮子,我拿了现成的Classic库。很简单(表面上看),不到100行代码,你可以看一下源码。
实际上,我对此感到困惑:我有一个“类”(实际上是库中的一个表,其中的字段__index就是它本身);“类”有一个扩展方法,它创建自己的副本,添加方法、元方法,并将自己分配为该副本的元表。现在我有一个这样的类的实例。我不知道如何附加上面显示的内容。如何在没有我参与的情况下将您的元方法分配(添加)到已经自动创建元方法的表。
下面是使用 OOP 的示例代码。他是个工人!我设法做我想做的事,但是 Classic 库的功能被破坏了,因为我覆盖了现有的 metamethod __index。
local Object = require "classic"
local T = Object:extend()
function T:new()
self.pos = {2, 4}
self.size = {8, 16}
setmetatable(self, {
__index = function(table, key)
if key == "x" then return table.pos[1]
elseif key == "y" then return table.pos[2]
elseif key == "w" then return table.size[1]
elseif key == "h" then return table.size[2]
end
end,
__newindex = function(table, key, value)
if key == "x" then table.pos[1] = value
elseif key == "y" then table.pos[2] = value
elseif key == "w" then table.size[1] = value
elseif key == "h" then table.size[2] = value
end
end
})
end
local t = T()
print(t.x) -- 2
t.x = 222
print(t.pos[1]) -- 222
print(t:is(Object)) -- error! функционал Classic нарушен!
很抱歉,这个问题变得相当混乱和令人困惑。我的问题是我很困惑。
UPD:我试图self.__index()在我的新函数中添加__index(),希望先执行旧函数,然后执行新函数,但一切都比我想要的复杂,结果我得到堆栈溢出:)
我不知道它还会在哪里爆炸,但它似乎是这样工作的: