Рекомендуемый способ рекурсивно ссылаться на 2+ модуля в Lua 5.2
Есть ли способ иметь
- Два модуля Lua (назовем их
A
а такжеB
) - Каждый модуль использует функции другого, поэтому они должны
require
друг с другом - Третий модуль (назовем его
C
) можешь использоватьA
но нетB
например
C.lua
:
local A = require 'A'
-- ...
A.foo()
- Там может быть другой модуль
D
что требуетB
но нетA
и / илиE
требуя какA
а такжеB
- ни
A
ниB
ни их члены не должны быть добавлены в глобальное пространство имен. - Избегайте использования
module
а такжеsetfenv
функции (устарело в Lua 5.2)
Связанный: Lua - как мне использовать одну библиотеку из другой? (примечание: это решение не обрабатывает циклические зависимости.)
3 ответа
Я нашел довольно простой способ сделать это:
A.lua
:
local A = {}
local B
function A.foo()
B = B or require 'B'
return B.bar()
end
function A.baz()
return 42
end
return A
B.lua
:
local B = {}
local A
function B.bar()
A = A or require 'A'
return A.baz()
end
return B
Другой метод, предложенный Оуэном Шепардом в списке рассылки lua-l:
Если мы установим package.loaded[current-module-name]
вверху каждого модуля, затем любой другой модуль require
Позже я могу обратиться к текущему (возможно, неполному) модулю.
A.lua:
local A = {}
package.loaded[...] = A
local B = require 'B'
function A.foo()
return B.bar()
end
function A.baz()
return 42
end
return A
B.lua:
local B = {}
package.loaded[...] = B
local A = require 'A'
function B.bar()
return A.baz()
end
return B
Это не будет работать везде. Например, если B
инициализация зависит от A.baz
тогда он потерпит неудачу, если A
загружается первым, потому что B
увидим неполную версию A
в котором baz
еще не определено.
Стандартный способ сделать это на любом языке - это ввести посредника. Затем модули могут публиковать и подписываться на посредника. http://en.wikipedia.org/wiki/Mediator_pattern
Примером этого в моих языках является шина mvccontrib, IEventAggregator и класс MVVM Lite Messenger. Все они делают одно и то же.