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:
obj:method(a,b,c)
is exactly equivalent to obj.method(obj,a,b,c)
obj.method
is exactly equivalent to obj["method"]
.
- 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.