нужна помощь в понимании метаметода таблицы, установленной для этой таблицы - PullRequest
0 голосов
/ 13 января 2019

Я не уверен, какой смысл устанавливать метаметод стека в стек.

Я оглянулся, но ни одно из объяснений не имело слишком большого смысла. Я понимаю, что иногда экземплярам может понадобиться использовать Stack для каких-либо отсутствующих методов, но я надеялся получить более четкое объяснение.

Stack = {} Stack.__index = Stack

1 Ответ

0 голосов
/ 13 января 2019

Допустим, у вас есть "2d vector" "класс", который имеет .x и .y. Вы пишете dotproduct функцию для них:

function dotproduct(a, b)
    return a.x * b.x + a.y * b.y
end

Самый простой способ написать foo:dot(bar) - это установить свойство .dot для каждого нового экземпляра:

-- Make a "V2" namespace
local V2 = {}
function V2.new(x, y)
    return {
        x = x,
        y = y,

        -- Attach any methods to the object, also
        dot = dotproduct,
    }
end

Однако с ростом числа методов ситуация ухудшается по двум причинам. Во-первых, ваши объекты становятся больше - даже если вам нужно держать только два числа в каждом векторе, большинство хеш-таблиц - это функции, которые всегда одинаковы! Другая причина заключается в том, что множественные конструкторы становятся сложными, потому что вам нужно дублировать работу в каждом конструкторе.

Решением этой проблемы является __index метатабельный. Вместо того, чтобы копировать каждый метод на каждый новый объект, вы можете просто указать, где найти «недостающие» методы по мере необходимости:

V2.dot = dotproduct
function V2.new(x, y)
    return setmetatable({x = x, y = y}, {__index = V2})
end

У этой конструкции есть небольшой недостаток. Во-первых, вы выделяете новую метатаблицу в дополнение к каждой таблице, что является пустой тратой памяти (все метатаблицы одинаковы). Во-вторых, у вас нет возможности переопределить другие методы, не увеличивая эту новую метатабельность (то же раздражение, что и раньше).

Итак, мы просто делаем V2 метатабельным * :

V2.__index = V2
function V2.new(x, y)
   return setmetatable({x = x, y = y}, V2)
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...