2

我有以下课程

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],如果它不是零。

现在我正在尝试对成员函数做同样的事情。即如果我调用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 

但是这里有两件事不对。

  1. 我无法检索原始函数的参数
  2. 事件如果我只是访问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 传递。

希望这是有道理的。

4

1 回答 1

6

对更新帖子的回应:

progress_object 作为第一个参数传递给 showSum。但我需要通过 group_object

如果您要忽略调用方法的对象的状态,并替换其他对象的状态,为什么它甚至是该对象上的方法?这就像重写加法运算符来进行乘法一样,这是一种混淆的方法。

换句话说,你想要这个:

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

回复原帖:

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

我该如何做到这一点?

没做什么。您的原始代码处理此问题。

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

记住:

  1. obj:method(a,b,c)完全等同于obj.method(obj,a,b,c)
  2. obj.method完全等价于obj["method"]
  3. 您的代码已经解析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]
     if type(val) == "function" then 
         self.__group:val()
         return function() end 
     end

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

于 2012-06-27T22:53:49.493 回答