Использование 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)
Другие вопросы по тегам