Lua的元表和元方法 - 如何调用不同的成员函数(Lua metatables and metame

2019-07-30 03:56发布

我有以下类

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不调用它,该函数将被调用

我已经得到了我想要的东西复杂化的感觉和解决方案的方式更简单。

任何帮助表示赞赏。

UPDATE

@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 .__基)作为自代替progress_object。

希望是有道理的。

Answer 1:

应对更新的帖子:

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] (除非键==“VAL”),那么你通过调用者一个函数,它什么都不做。



文章来源: Lua metatables and metamethod - How to call a different member function