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

Я установил в моем скрипте систему "psuedo-oop", которая позволяет мне лучше взаимодействовать с данными пользователя из моего приложения. Моя система работает замечательно хорошо, за исключением того, что она не передает ссылки, она передает значения. Из-за этого, если я скажу что-то вроде:

World.Body.Parent=World.Body2

Ничего на самом деле не происходит, потому что это никогда не устанавливает BodyРодитель другого тела. Вместо этого это как бы упрощается:

World=World.Body2

(Так как World является родителем Body так что возвращается). Теперь, если я сделаю что-то подобное, с другой стороны:

print(World.Body.Parent.Type)

==> World

Потому что он правильно получил World объект (будучи родителем Body).

Теперь, имея в виду все это, есть ли какой-нибудь способ убедиться, что он передается больше по ссылке, а не по факту отправки объекта? Любые идеи были бы хорошы!

Вот соответствующий исходный код, который я использую:

local target=_G

function AddService(service)
    Blank=(function(...) return end)
    CreateTemporaryIndex=(function(obj)
        local env_meta={
            __index=(function(this, key)
                if obj[key]~=nil and obj[key]~=key then
                    if type(obj[key]) ~= "userdata" then
                        return obj[key]
                    else
                        local r,i=pcall(function() Blank(obj[key].Type) end)
                        if r then
                            return CreateTemporaryIndex(obj[key])
                        else
                            return (function(...) local arg={...} table.remove(arg,1) return obj[key](obj,unpack(arg)) end)
                        end
                    end
                else
                    local ofObj=obj:Child(key)
                    if ofObj~=nil then
                        return CreateTemporaryIndex(ofObj)
                    end
                end
                return nil
            end)
        }
        local nRe={}
        setmetatable(nRe,env_meta)
        return nRe
    end)
    target[service.Name]=CreateTemporaryIndex(service)
end

AddService(__Environment.World)
AddService(__Environment.Players)
AddService(__Environment.Lighting)
AddService(__Environment.Environment)

1 ответ

Решение

Метаметод __index вызывается только при доступе к свойствам. Для реализации пользовательского установщика вам также необходимо определить метаметод __newindex. Вы можете найти больше информации в разделе руководства Lua, на которое я ссылаюсь.

Тем не менее, на вашем месте я бы снова подумал, действительно ли нужно все это усложнение таблицы прокси. В качестве примера одного из небольших угловых случаев, которые вы, возможно, не рассмотрели, перебор ваших сред с парами и ipairs завершится неудачей, если вы не добавите также метаметоды __ipairs и __pairs.

Другие вопросы по тегам