Lua元表和元方法 - 如何调用不同的成员函数
2012-6-28 2:57:27
收藏:0
阅读:176
评论:1
我有以下的类:
local PROGRESS = {}
PROGRESS.__index = function(self,key)
if key~="__group" and self.__group[key] then
return self.__group[key]
else
return rawget(self,key)
end
end
当你访问 table[key] 时,它会在 table.__group 中执行一次查找(table.__group 是另一个类的对象),如果它不是空值,则返回 table.__group[key] 。
现在我想为成员函数做同样的事情。也就是说,如果我调用 table:key() ,则必须在 table.__group 中执行查找,如果该函数存在,则应调用 table.__group:key()。
我该如何实现它呢?
我尝试做如下操作:
local PROGRESS = {}
PROGRESS.__index = function(self,key)
if key~="__group" and self.__group[key] then
local val = self.__group[key]
if type(val) == "function" then
self.__group:val()
return function() end
end
return self.__group[key]
else
return rawget(self,key)
end
end
但有两件事情是错误的。
- 我无法获取原始函数的参数
- 即使我只是访问
table[key].function而没有调用它,该函数也会被调用。
我觉得我在试图把事情复杂化,解决方案应该更简单。
任何帮助都将不胜感激。
更新
@ Mud
原始代码的问题在于传递给成员函数的对象是新类的对象,而不是旧类的对象。
考虑此代码
GROUP_CLASS = {}
GROUP_CLASS.__index = GROUP_CLASS
function GROUP_CLASS:showSum(a,b) print(self);print(a + b) end
group_object = setmetatable({},GROUP_CLASS)
group_object:showSum(1,2)
local PROGRESS_CLASS = {}
PROGRESS_CLASS.__index = function(self,key,value)
if key~="__group" and self.__group[key] then
return self.__group[key]
else
return rawget(self,key)
end
end
progress_object = setmetatable( {__group = group_object} , PROGRESS_CLASS)
progress_object:showSum(3,3)
--progress_object is passed as first argument to showSum. But i need group_object to be passed
在上面的代码中,当调用 progress_object:showSum(3,3) 时,是否可能将 group_object(也就是 progress_object.__group)作为 self 传递,而不是 progress_object。
希望有意义。
点赞
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
回应更新过的帖子:
如果您要忽略调用方法的对象的状态,并替换为其他对象的状态,那么为什么它甚至是该对象的方法?这就像覆盖加法运算符以执行乘法,这是一种混淆的方法。
换句话说,您希望这样做:
progress_object:method("foo")通过奇怪的内部机制解决,变成这样:
group_object:method("foo")为什么不跳一步直接进行后者的调用呢?
如果您必须这样做,则可以通过返回替换“self”为“__group”的方法的代理来实现
local PROGRESS_CLASS = {} PROGRESS_CLASS.__index = function(self, key) local groupval = self.__group[key] if key == '__group' or not groupval then return rawget(self, key) elseif type(groupval) ~= 'function' then return groupval else return function(...) if self == ... then -- method call -- replace self argument with __group return groupval(self.__group, select(2, ...)) else return groupval(...) end end end end回应原帖子:
什么也不用做。您原来的代码已经处理了这个问题。
Lua不知道什么是“成员函数”。成员是成员(即表中的元素),而成员的_value_是否为函数无关紧要。
请记住:
obj:method(a,b,c)等同于obj.method(obj,a,b,c)obj.method等同于obj ["method"]。obj ["method"]解析为obj.__group ["method"]所以你完成了。
例如,假设我们有:
group = {} function group:showSum (a,b) print(a + b) end function group:showProduct(a,b) print(a * b) end使用您的第一个代码,我们可以编写:
foo = setmetatable({__group = group},PROGRESS) foo:showSum(3,3)-6 foo:showProduct(3,3)-9就这样。
现在,只要我们在这里,让我们看看您的第二个函数正在做什么:
local val = self.__ group [key] 如果type(val)==“function” then self.__group:val() 返回function()end end首先,从
__group获取函数值。在这一点上,你已经完成了。只需返回该值,调用方将调用该值(即(...))。相反,您调用了__ group [“val”],这很可能是与__group [key](除非 key==“val”)完全不同的函数,然后将调用者传递给一个什么都不做的函数。