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

查看:216
本文介绍了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](如果它不是nil的话).

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.

感谢您的帮助.

更新

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

@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 calltable: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不知道什么是成员函数".成员是成员(即表中的元素),并且该成员的 value 是否是函数无关.

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

就是这样.

现在,只要我们在这里,就让我们看看您的 second 函数在做什么:

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天全站免登陆