2012-06-27 1 views
2

У меня есть следующий класс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], если это не ноль.

Теперь я пытаюсь сделать то же самое для функций-членов. i.e Если я звоню 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 

Но здесь есть 2 вещи.

  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.

Надеюсь, что имеет смысл.

ответ

5

Ответ на обновленный пост:

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 

Ответ на исходное сообщение:

Как Я пытаюсь сделать то же самое для функций-членов. i.e Если я вызываю 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"), то вы передаете вызывающей функции, которая ничего не делает.

+0

Ах! Много смысла. Иногда я думаю слишком много: D Спасибо большое! – SatheeshJM

+0

Эй. Исходный код имеет небольшую проблему. Обновите вопрос. Вы можете помочь с этим? Кстати, именно поэтому я разместил этот вопрос. Забыл проблему, когда я прочитал ваш ответ: P – SatheeshJM

+0

@SatheeshJM Я обновил сообщение. – Mud