Lua metatables and metamethod - How to call a different member function

后端 未结 1 1280
独厮守ぢ
独厮守ぢ 2021-01-22 15:20

I have the following Class

local PROGRESS = {}

PROGRESS.__index = function(self,key)

    if key~=\"__group\" and self.__group[key] then 
        return  self._         


        
相关标签:
1条回答
  • 2021-01-22 16:03

    Response to updated post:

    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?

    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
    

    Response to original post:

    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.

    How do I accomplish this?

    Do nothing. Your original code handles this.

    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.

    Remember:

    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"]

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

    0 讨论(0)
提交回复
热议问题