[英]Lua metatables and metamethod - How to call a different member function
I have the following Class 我有以下课程
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
What this does is when You access table[key]
it performs a lookup in table.__group
(which is an object of another class) and returns table.__group[key]
,if it is not nil. 这是什么,当您访问
table[key]
它将在table.__group
(这是另一个类的对象)中执行查找,并返回table.__group[key]
(如果它不是nil)。
Now I am trying to do the same for member functions. 现在,我尝试对成员函数执行相同的操作。 ie If I call
table:key()
a lookup must be performed in table.__group
and if the function is present, then table.__group:key()
should be called. 即如果我调用
table:key()
必须在table.__group
执行查找,并且如果存在该函数,则应该调用table.__group:key()
。
How do I accomplish this? 我该如何完成?
I tried to do this. 我试图做到这一点。
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
But there are 2 things wrong here. 但是这里有两件事是错误的。
table[key].function
without calling it, the function will be called table[key].function
而没有调用它,则该函数将被调用 And I've got the feeling that I am trying to complicate things and the solution is way simpler. 而且我有一种使事情变得复杂的感觉,并且解决方案更简单。
Any help is appreciated. 任何帮助表示赞赏。
UPDATE UPDATE
@Mud The problem with the original code is that the object passed as 'self' to the member function is an object of the new class. @Mud原始代码的问题在于,作为“自身”传递给成员函数的对象是新类的对象。 Not of the old class.
不是老套的。
Consider this code 考虑这段代码
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
In the above code, When progress_object:showSum(3,3)
is called, is it possible to pass group_object (or in other words progress_object.__group) as self instead of progress_object. 在上面的代码中,当调用
progress_object:showSum(3,3)
,是否可以将group_object(或称为progress_object .__ group)作为自身而不是progress_object传递。
Hope that makes sense. 希望有道理。
Response to updated post: 对更新后的帖子的回复:
progress_object is passed as first argument to showSum.
将progress_object作为第一个参数传递给showSum。 But i need group_object to be passed
但是我需要通过group_object
If you're going to ignore the state of the object a method is called on, and substitute the state of some other object, why is it even a method on that object? 如果要忽略对象的状态,则调用一个方法,并替换其他对象的状态,为什么它甚至是该对象上的方法? That's like overriding the addition operator to do multiplication, a recipe for confusion.
这就像重写加法运算符进行乘法一样,这是造成混淆的秘诀。
In other words, you want this: 换句话说,您想要这样:
progress_object:method("foo")
To resolve, via bizarre internal machinery, into this: 通过怪异的内部机制解决:
group_object:method("foo")
Why not skip a step and just make the latter call? 为什么不跳过一步而只打后面的电话呢?
If you must , you could achieve this by returning a proxy for the method which replaces self
with __group
如果必须的话 ,可以通过返回用
__group
代替self
的方法的代理来实现
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
Response to original post: 对原始帖子的回复:
How I am trying to do the same for member functions.
我如何尝试对成员函数执行相同的操作。 ie If I call
table:key()
a lookup must be performed intable.__group
and if the function is present, thentable.__group:key()
should be called.即如果我调用
table:key()
必须在table.__group
执行查找,并且如果存在该函数,则应该调用table.__group:key()
。How do I accomplish this?
我该如何完成?
Do nothing. 没做什么。 Your original code handles this.
您的原始代码可以处理此问题。
Lua doesn't know what a "member function" is. Lua不知道什么是“成员函数”。 A member is a member (ie an element in a table), and whether the value of that member is a function is irrelevant.
成员是成员(即表中的元素),并且该成员的值是否为函数无关。
Remember: 记得:
obj:method(a,b,c)
is exactly equivalent to obj.method(obj,a,b,c)
obj:method(a,b,c)
完全等同于obj.method(obj,a,b,c)
obj.method
is exactly equivalent to obj["method"]
. obj.method
与obj["method"]
完全等效。 obj["method"]
into obj.__group["method"]
obj["method"]
解析为obj.__group["method"]
So you're done. 这样就完成了。
For instance, say we have: 例如,假设我们有:
group = {}
function group:showSum (a,b) print(a + b) end
function group:showProduct(a,b) print(a * b) end
Using your first code, we can write: 使用您的第一个代码,我们可以编写:
foo = setmetatable({__group = group}, PROGRESS)
foo:showSum(3,3) -- 6
foo:showProduct(3,3) -- 9
That's it. 而已。
Now, as long as we're here, let's look at what your second function is doing: 现在,只要我们在这里,就让我们看看第二个函数在做什么:
local val = self.__group[key]
if type(val) == "function" then
self.__group:val()
return function() end
end
First you grab the function value from __group
. 首先,您从
__group
获取函数值。 At this point you're done. 至此,您已经完成。 Simply return that value, and the caller is going to call that value (ie
(...)
). 只需返回该值,调用者便会调用该值(即
(...)
)。 Instead, you call __group["val"]
which is likely a totally different function from __group[key]
(unless key=="val"), then you pass the caller a function which does nothing. 而是,您调用
__group["val"]
可能与__group[key]
完全不同(除非key ==“ val”),然后再向调用方传递一个不执行任何操作的函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.