Использование метатаблиц в Lua - PullRequest
2 голосов
/ 18 ноября 2011

Я пытаюсь реализовать нотацию объектов в скриптах Lua.Вот что мне удалось сделать с C API:

  • Я создал новую глобальную таблицу «Test» как класс и добавил в нее поле «new», указывающее на функциюнаписано на C, т.е. я могу сделать это в коде lua: "local obj = Test.new ()" (вызывает функцию "new")

  • "новая" функция C создаети возвращает новую таблицу, и регистрирует функции в ней как поля (например, «add», «count» ...), т.е. я могу сделать это: «obj: add (« mike »)» и «obj: count ()»(obj передается в качестве первых аргументов с нотацией ":")

2 вопроса:

1) Все работает, как и ожидалось, но мне интересно вот что: В чем преимущество использования метатаблицы в моем случае?Я вижу везде, что метатаблицы могут помочь мне достичь того, что я пытался сделать, но я не понимаю, где они будут полезны?Добавление полей в таблицы как методы не правильно?Как метатаблицы могут помочь мне (если они добавлены как метатаблицы моих таблиц)?

2) На самом деле я пытаюсь воспроизвести поведение C ++ в Lua здесь.Например, когда я пишу это в C ++: «Test * obj = new Test ();»Я ожидаю, что C ++ и конструктор Test вернут мне указатель экземпляра Test.Это именно то, что я пытаюсь сделать для меня Lua.

Дело в том, что в этом случае я использую таблицу в качестве возврата «new», но не указатель, поэтому я могу вызывать методы дляпозже с Lua (используя его поля), как стандартный объект C ++ (с оператором ->).

Чтобы иметь возможность получить фактический указатель моего класса в функциях C, я добавил поле "ptr "(light uservalue) в таблицу, возвращаемую" new ".Без него я мог бы манипулировать только таблицей Lua в моей функции C, и ничего более (поэтому больше не нужно вызывать методы для реального указателя).

Мой второй вопрос: правильный ли это способсделай это?У вас есть идея, как можно манипулировать моим указателем везде без этого поля "ptr"?

Спасибо,

Николас.

Ответы [ 2 ]

3 голосов
/ 18 ноября 2011

Основная причина в том, что вы получаете метаметод __index.Без этого каждый экземпляр объекта должен иметь все функции, связанные с ним: что может сделать таблицы большими;и использовать много памяти.

local methods = { 
    foo = function() return "foo" end ;
    bar = function() return "bar" end ;
    bob = function() return "bob" end ;
    hen = function() return "hen" end ; 
}

Таким образом, у вас есть либо

function new_no_mt ( )
    local t = {}
    for k , v in pairs ( methods ) do t [ k ] = v end
    return t
end

против

local mt = { __index = methods ; }
function new_mt ( )
    return setmetatable ( { } , mt )
end

Есть и другие преимущества;

  • определение операторов;
  • простое сравнение типов посредством сравнения метатаблиц.
  • Изменение метода в метатаблице изменяет его для всех объектов, но изменение его только для одного объекта меняет его только для этого объекта.

В противном случае то, что вы пытаетесь сделать, звучит как идеальная ситуация для пользовательских данных.Пользовательские данные могут быть проиндексированы только при наличии метатода __index (нет таблицы для добавления методов)

3 голосов
/ 18 ноября 2011

В чем преимущество использования метатаблиц в моем случае?

Вот один из них.

Test.new = function() end

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

Вот еще один:

local myTest = Test()

Вы не можете сделать это безметатабельный (перегрузить метаметод __call).И это выглядит намного более естественным для синтаксиса Lua, чем вызов Test.new.

И еще:

local testAdd = Test() + Test()

Перегрузка оператора.Вы не можете сделать это без метатаблиц.

Также:

Это именно то, что я пытаюсь сделать Луа для меня.

Вотсовет: не надо.

Разные языки по разным причинам.Вы должны делать вещи в Lua Lua , а не в C ++.Я могу понять, что хочу предоставить определенные механизмы C ++ (например, перегрузку и т. Д.), Но вы не должны использовать new только потому, что это то, что использует C ++.

Кроме того, существует множество библиотек, которые выполняют эту работудля тебя. SWIG и Luabind - два больших.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...