Обработчик событий Lua - PullRequest
       2

Обработчик событий Lua

5 голосов
/ 29 ноября 2011

Есть ли в lua встроенный "обработчик событий" или у него есть библиотека, доступная для этого?

Так, например, когда "a = 100" происходит событие.1004 * Что-то еще вместо использования:

while true do
 if a == 100 then
   [...]
   break;
 end
end

Или просто добавление сна в него.«Пока правдивый поступок» - всего лишь пример, но ужасный.

1 Ответ

16 голосов
/ 29 ноября 2011

Lua работает в однопоточном режиме, поэтому любая проверка должна быть явно выполнена вашим кодом.

Процесс выполнения кода сразу после изменения переменной известен как «наблюдение».

Если вы программируете в среде, где набор кода выполняется каждый кадр (например, игра), вы можете проверить это вручную.Например:

WatchedVariables = {
    a = 5,
    b = 22,
}
WatchedVariables_cache = {}
for k,v in pairs(WatchedVariables) do
    WatchedVariables_cache[k] = v
end

function OnFrame()
    print("NEXT FRAME! (possibly 1 second later or something)")
    for k,v in pairs(WatchedVariables) do
        local v_old = WatchedVariables_cache[k]
        if v ~= v_old then
            -- this is the "callback"
            print(tostring(k).." changed from "..tostring(v_old).." to "..tostring(v))

            WatchedVariables_cache[k] = v
        end
     end
 end

 function SomeFunctionThatOperatesSomeTime()
     print("about to change a, brother!")
     WatchedVariables.a = -7
     print("a is changed")
 end

После следующего кадра будет выполнен код обратного вызова (печать).Недостатком этого подхода является то, что код обратного вызова не печатается сразу после того, как WatchedVariables.a установлено на -7, то есть: вывод будет:

about to change a, brother!
a is changed
NEXT FRAME! (possibly 1 second later or something)
a changed from 5 to -7

Для предотвращенияВ этом потенциально нежелательном поведении может использоваться функция setter , например:

MyObject = {
    _private_a = 5,
    set_a = function(self, new_value_of_a)
        self._private_a = 5
        -- callback code
        print("a set to "..tostring(new_value_of_a))
    end,
    get_a = function(self)
        return self._private_a
    end
}

function SomeFunctionThatOperatesSomeTime()
     print("about to change a, brother!")
     MyObject:set_a(-7)
     print("a is changed")
 end

Вывод этого кода показывает, что обратный вызов выполняется немедленно:

about to change a, brother!
a set to -7
a is changed

Чтобы сделать это более удобным, Lua предоставляет metatables , которые делают такое поведение прозрачным для программиста.Пример:

MyObject = {
    __privates = {
        a = 5,
    }
}
MyObject_meta = {
    __index = function(self, k)
        return rawget(self, "__privates")[k]
    end,
    __newindex = function(self, k, v)
        rawget(self, "__privates")[k] = v
        -- callback code
        print("a set to "..tostring(v))
    end,
}
setmetatable(MyObject, MyObject_meta)

function SomeFunctionThatOperatesSomeTime()
     print("about to change a, brother!")
     MyObject.a = -7
     print("a is changed")
 end

Вывод этого кода будет таким же, как в предыдущем примере:

about to change a, brother!
a set to -7
a is changed

Вот реализация для вашего примера:

MyObject = {
    __privates = {
        a = 5,
    }
    __private_callback = function(self, k, ov, v)
        if k == "a" and v == "100" then
            print("a is 100!")
        end
    end
}
MyObject_meta = {
    __index = function(self, k)
        return rawget(self, "__privates")[k]
    end,
    __newindex = function(self, k, v)
        local privates = rawget(self, "__privates")
        local ov = privates[k]
        privates[k] = v
        rawget(self, "__private_callback")(self, k, ov, v)
    end,
}
setmetatable(MyObject, MyObject_meta)

function SomeFunctionThatOperatesSomeTime()
     MyObject.a = -7 -- prints nothing
     MyObject.a = 100 -- prints "a is 100!"
     MyObject.a = 22 -- prints nothing
 end

Почему переменные __privates и __private_callback имеют префикс с двумя подчеркиваниями? Общепринятым является префикс закрытых членов, к которым нельзя обращаться в типичных ситуациях программирования, с двумя подчеркиваниями.Если вы знакомы с объектно-ориентированной методологией и ее реализацией на таких языках, как Java и C ++, вы поймете, как она похожа на ключевые слова private и protected.

Если вы знакомы с C #языком, вы можете увидеть, как set_a / get_a и метатабельные реализации похожи на средства доступа (set / get).

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