Lua 元表和元方法 - 如何调用不同的成员函数 [英] Lua metatables and metamethod - How to call a different member function

查看:24
本文介绍了Lua 元表和元方法 - 如何调用不同的成员函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下课程

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[key] ,如果它不为零.

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() 应该被调用.

Now I am trying to do the same for member functions. i.e 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.

我该如何实现?

我试图这样做.

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. 我无法检索原始函数的参数
  2. 事件如果我只是访问table[key].function而不调用它,该函数将被调用
  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

而且我有一种感觉,我试图将事情复杂化,而解决方案要简单得多.

And I've got the feeling that I am trying to complicate things and the solution is way simpler.

感谢任何帮助.

更新

@泥原始代码的问题在于,作为self"传递给成员函数的对象是新类的对象.不是老班.

@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. Not of the old class.

考虑这个代码

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传递.

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.但我需要传递 group_object

progress_object is passed as first argument to showSum. But i need group_object to be passed

如果您要忽略调用方法的对象的状态,并替换某个其他对象的状态,为什么它甚至是该对象上的方法?这就像覆盖加法运算符进行乘法一样,这是一个混淆的秘诀.

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?

如果您必须,您可以通过返回将self替换为__group

If you must, you could achieve this by returning a proxy for the method which replaces self with __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


回复原帖:

我如何尝试为成员函数做同样的事情.即如果我调用 table:key(),必须在table.__group 中执行查找,并且如果该函数存在,则table.__group:key() 应该被调用.

How I am trying to do the same for member functions. i.e 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.

我该如何实现?

什么都不做.您的原始代码会处理此问题.

Do nothing. Your original code handles this.

Lua 不知道什么是成员函数";是.成员是成员(即表中的元素),与该成员的是否为函数无关.

Lua doesn't know what a "member function" is. A member is a member (i.e. an element in a table), and whether the value of that member is a function is irrelevant.

记住:

  1. obj:method(a,b,c) 完全等同于 obj.method(obj,a,b,c)
  2. obj.method 完全等同于 obj[method"].
  3. 您的代码已经将 obj["method"] 解析为 obj.__group["method"]
  1. obj:method(a,b,c) is exactly equivalent to obj.method(obj,a,b,c)
  2. obj.method is exactly equivalent to obj["method"].
  3. Your code already resolves obj["method"] into obj.__group["method"]

大功告成.

例如,假设我们有:

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

就是这样.

现在,只要我们在这里,让我们看看您的第二个函数在做什么:

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

首先从 __group 获取函数值.在这一点上你就完成了.只需返回该值,调用者就会调用该值(即 (...)).相反,您调用 __group[val"] 这可能是与 __group[key] 完全不同的函数(除非 key==val"),然后您向调用者传递一个什么都不做的函数.

First you grab the function value from __group. At this point you're done. Simply return that value, and the caller is going to call that value (i.e. (...)). 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.

这篇关于Lua 元表和元方法 - 如何调用不同的成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆