2016-03-25 4 views
3

Я пытаюсь реализовать простую наследование в Lua, как это представлено в PIL 16.2. Тем не менее, я столкнулся с удивительным поведением: метаметоды, похоже, не унаследованы. В следующем примере я создаю класс Point с x и y членами и даю ему метаметод __add. При добавлении экземпляров Point все работает нормально, но если я создаю подкласс и добавляю его, я получаю сообщение об ошибке.Не содержит ли наследование Lua метаметоды?

Point = {} 

function Point:new(x, y) 
    local point = {} 
    setmetatable(point, self) 
    self.__index = self 
    point.x = x or 0 
    point.y = y or 0 
    return point 
end 

Point.__add = function(a, b) 
    return Point:new(a.x + b.x, a.y + b.y) 
end 

p = Point:new(2,2) 
r1 = p + p 
print(p.x, p.y) -- prints "4 4" as expected 


ChildPoint = Point:new() 
c = ChildPoint:new() 

r2 = c + c -- Error: attempt to perform arithmetic on a table value (local 't1') 
print(r.x, r.y) 

Я ожидал, что Lua будет искать __add в ChildPoint, и которые вызывают бы ChildPoint «s __index, находя __add в Point. Но это, похоже, не происходит.

Почему это не работает, что на самом деле происходит, и (если это правильное поведение, а не просто моя ошибка), как реализовать наследуемые метаметоды в Lua?

+0

К сожалению, метаметоды не наследуются (я не знаю почему). Руководство Lua гласит: «Обратите внимание, что запросы для метаметодов всегда являются сырыми, а доступ к метаметоду не вызывает другие метаметоды». Вы можете скопировать все элементы '__ *' из старого метатебельного в новый при создании подкласса (в этом случае вы должны создать подкласс с другой функцией, чем создать экземпляр). Но это решение не приятно. –

ответ

2

Как объяснил Егор, метамотоды должны быть явно скопированы в этом случае; см. это ранее SO question для обсуждения той же проблемы и возможных решений (выбранная копирует метаметоды).