Lua:如何避免循环引用

13

问题

如何避免在尝试进行循环 require 时出现 Lua 5.1 中的以下错误?

$ lua main.lua 
lua: ./bar.lua:1: loop or previous error loading module 'foo'
stack traceback:
    [C]: in function 'require'
    ./bar.lua:1: in main chunk
    [C]: in function 'require'
    ./foo.lua:1: in main chunk
    [C]: in function 'require'
    main.lua:1: in main chunk
    [C]: ?

文件结构

main.lua

require "foo"
require "bar"
print (Foo.getName())
print (Bar.getName())

foo.lua

require 'bar'
Foo = {}
Foo.name = 'foo'

function Foo:getName()
    return Foo.name .. Bar.name
end

bar.lua

require 'foo'
Bar = {}
Bar.name = 'bar'

function Bar:getName()
    return Bar.name .. Foo.name
end

预期输出

$ lua main.lua 
foobar
barfoo

3
紧密相关(但针对Lua5.2,避免使用全局变量):https://dev59.com/El3Va4cB1Zd3GeqPBpKr - finnw
2个回答

14

解决方案

main.lua

Foo = Foo or require "foo"
Bar = Bar or require "bar"
print (Foo.getName())
print (Bar.getName())

foo.lua

Foo = {}
Bar = Bar or require "bar"
Foo.name = 'foo'

function Foo:getName()
    return Foo.name .. Bar.name
end

return Foo

bar.lua

Bar = {}
Foo = Foo or require "foo"
Bar.name = 'bar'

function Bar:getName()
    return Bar.name .. Foo.name
end

return Bar

解释

由于你正在设置全局变量,因此在尝试另一个 require 之前,可以检查文件是否已被要求(即全局已定义):

Bar = Bar or require "bar"

你的bar.lua文件必须返回Bar的定义;

Bar = {}
-- ...
return Bar

这并不能完全解决问题,因为 bar.lua 要求定义了 Foo。为了解决这个问题,您可以定义一个同名的虚拟变量:

这不会完全解决问题,因为 bar.lua 期望定义 Foo。要解决这个问题,您可以定义一个相同名称的虚拟变量:

Foo = {}
Bar = Bar or require "bar"

这只有在您推迟使用Foo直到调用函数时才可能实现。如果您想要从bar.lua的范围内调用Foo.name,那么您将遇到相同的循环依赖问题。


13
另一种解决该问题的方式是更改代码结构并将“共同”功能提取到第三个模块中,FooBar 都需要它。

4
最终,这肯定是我采取的方法,可以提供更好的依赖树。在这种情况下,我对允许循环依赖的解决方案感到好奇。谢谢! - Jess Telford

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接