简体   繁体   English

Lua元表和元方法-如何调用其他成员函数

[英]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. 但是这里有两件事是错误的。

  1. I am unable to retrieve the original function's arguments 我无法检索原始函数的参数
  2. Event if I just ACCESS 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 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? 我该如何完成?

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: 记得:

  1. 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)
  2. obj.method is exactly equivalent to obj["method"] . obj.methodobj["method"]完全等效。
  3. Your code already resolves 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM