tl; dr:什么设计模式允许您将Lua代码分割为多个文件,这些文件需要在不影响全局表的情况下共享某些信息?
在Lua中创建库需要库影响全局命名空间被认为是不好的形式:
--> somelib.lua <--
SomeLib = { ... }
--> usercode.lua <--
require 'somelib'
print(SomeLib) -- global key created == bad
Run Code Online (Sandbox Code Playgroud)
相反,最好的做法是创建一个使用局部变量的库,然后返回它们以供用户根据需要进行分配:
--> somelib.lua <--
local SomeLib = { ... }
return SomeLib
--> usercode.lua <--
local theLib = require 'somelib' -- consumers name lib as they wish == good
Run Code Online (Sandbox Code Playgroud)
使用单个文件时,上述模式工作正常.但是,当您有多个相互引用的文件时,这会变得相当困难.
如何重写以下文件套件以使断言全部通过?理想情况下,重写将在磁盘上保留相同的文件,并为每个文件保留责任.(通过将所有代码合并到单个文件中进行重写是有效的,但没有帮助;)
--> test_usage.lua <--
require 'master'
assert(MASTER.Simple)
assert(MASTER.simple)
assert(MASTER.Shared)
assert(MASTER.Shared.go1)
assert(MASTER.Shared.go2)
assert(MASTER.Simple.ref1()==MASTER.Multi1)
assert(pcall(MASTER.Simple.ref2))
assert(_G.MASTER == nil) -- Does not currently pass
Run Code Online (Sandbox Code Playgroud)
--> master.lua <--
MASTER = {}
require 'simple'
require 'multi'
require 'shared1'
require 'shared2'
require 'shared3'
require 'reference'
--> simple.lua <--
MASTER.Simple = {}
function MASTER:simple() end
--> multi.lua <--
MASTER.Multi1 = {}
MASTER.Multi2 = {}
--> shared1.lua <--
MASTER.Shared = {}
--> shared2.lua <--
function MASTER.Shared:go1() end
--> shared3.lua <--
function MASTER.Shared:go2() end
--> reference.lua <--
function MASTER.Simple:ref1() return MASTER.Multi1 end
function MASTER.Simple:ref2() MASTER:simple() end
Run Code Online (Sandbox Code Playgroud)
我想通过自我引用将环境设置为主表来解决问题.require但是在调用函数时这不起作用,因为它们会改变环境:
--> master.lua <--
foo = "original"
local MASTER = setmetatable({foo="captured"},{__index=_G})
MASTER.MASTER = MASTER
setfenv(1,MASTER)
require 'simple'
--> simple.lua <--
print(foo) --> "original"
MASTER.Simple = {} --> attempt to index global 'MASTER' (a nil value)
Run Code Online (Sandbox Code Playgroud)
小智 4
您赋予 master.lua 两项职责:
相反,您应该为 (1) 创建一个单独的模块并将其导入所有子模块中:
--> common.lua <--
return {}
--> master.lua <--
require 'simple'
require 'multi'
require 'shared1'
require 'shared2'
require 'shared3'
require 'reference'
return require'common' -- return the common table
--> simple.lua <--
local MASTER = require'common' -- import the common table
MASTER.Simple = {}
function MASTER:simple() end
Run Code Online (Sandbox Code Playgroud)
ETC。
最后,更改第一行test_usage.lua以使用局部变量:
--> test_usage.lua <--
local MASTER = require'master'
...
Run Code Online (Sandbox Code Playgroud)
现在测试应该通过了。