Использование LuaJ со Scala
Я пытаюсь использовать LuaJ со Scala. Большинство вещей работает (фактически все работает, если вы делаете их правильно!), Но простая задача установки значений объектов стала невероятно сложной благодаря реализации сеттера в Scala.
Scala:
class TestObject {
var x: Int = 0
}
Lua:
function myTestFunction(testObject)
testObject.x = 3
end
Если я выполняю скрипт или строку, содержащую эту функцию Lua, и передаю принудительный экземпляр TestObject в myTestFunction, это вызывает ошибку в LuaJ. LuaJ пытается напрямую записать значение, а Scala требует, чтобы вы прошли через неявно определенный сеттер (с ужасным именем x_=, которое не является допустимым Lua, поэтому даже попытка вызвать его как функцию заставляет ваш Lua не анализировать),
Как я уже сказал, для этого есть обходные пути, например, определение собственного установщика или использование разметки @BeanProperty. Они просто делают код, который легко писать, гораздо сложнее:
Lua:
function myTestFunction(testObject)
testObject.setX(testObject, 3)
end
Кто-нибудь знает способ заставить luaj неявно вызывать сеттер для таких назначений? Или где я мог бы посмотреть в исходном коде luaj, чтобы реализовать такую вещь?
Спасибо!
2 ответа
Должен признать, что я не слишком знаком с LuaJ, но первое, что приходит мне в голову в связи с вашей проблемой, - это обернуть объекты в прокси-таблицы, чтобы облегчить взаимодействие с API. В зависимости от ваших потребностей, это решение может быть или не быть лучшим, но это может быть хорошим временным решением.
local mt = {}
function mt:__index(k)
return self.o[k] -- Define how your getters work here.
end
function mt:__newindex(k, v)
return self.o[k .. '_='](v) -- "object.k_=(v)"
end
local function proxy(o)
return setmetatable({o = o}, mt)
end
-- ...
function myTestFunction(testObject)
testObject = proxy(testObject)
testObject.x = 3
end
Я считаю, что это может быть наименее агрессивным способом решения вашей проблемы. Что касается изменения исходного кода LuaJ для лучшего соответствия вашим потребностям, я быстро просмотрел документацию и исходный код и нашел то, это и это. Мое лучшее предположение гласит, что в строке 71 файла JavaInstance.java вы найдете то, что вам нужно изменить, если в Scala требуется другой способ установки значений.
f.set(m_instance, CoerceLuaToJava.coerce(value, f.getType()));
Возможно, вам следует использовать синтаксис метода:
testObject:setX(3)
Обратите внимание на двоеточие ':' вместо точки '.' что может быть трудно различить в некоторых редакторах.
Это имеет тот же эффект, что и вызов функции:
testObject.setX(testObject, 3)
но более читабельно.
Его также можно использовать для вызова статических методов в классах:
luajava.bindClass("java.net.InetAddress"):getLocalHost():getHostName()
Часть слева от ':' оценивается один раз, поэтому такой оператор, как
x = abc[d+e+f]:foo()
будет оцениваться так, как если бы это было
local tmp = abc[d+e+f]
x = tmp.foo(tmp)