Oop Lua-如何动态调用模块?

Oop Lua-如何动态调用模块?,oop,module,lua,Oop,Module,Lua,下面是我正在使用的一些非常相似的Lua代码。我需要知道如何动态调用另一个模块(“zebra”): 这里有两个模块: local Avar = {} function Avar.new() return "avar" end return Avar local Bvar = {} function Bvar.new() return "new" end function Bvar.old() return "old" end return Bvar 如果我试图将字符串“a

下面是我正在使用的一些非常相似的Lua代码。我需要知道如何动态调用另一个模块(“zebra”):

这里有两个模块:

local Avar = {}

function Avar.new()
  return "avar"
end

return Avar

local Bvar = {}

function Bvar.new()
  return "new"
end

function Bvar.old()
  return "old"
end

return Bvar
如果我试图将字符串“avar”传递给我的“create”函数,它将不起作用。如果我传入没有引号的单词“avar”,它确实有效,但是,我不明白什么是没有引号的avar?好像是一张空白的桌子?不知道如何在我的主程序中将空白表作为参数传递


但也许我完全走错了路。如何动态调用模块?

avar
不带引号是您创建的全局变量。它被初始化为
require
function1返回的值,即您正在调用的模块返回的值。在本例中,它是一个带有
new
字段的表,该字段恰好是一个函数

1在Lua中导入模块是通过常规函数而不是特殊语法完成的。可以使用函数调用括号,因为如果使用单个参数编写函数调用,并且该参数是字符串或表,则括号是可选的

除此之外,还有其他一些事情让你感到困惑:

  • 您存储在
    avar
    上的表不是空的!您可以通过对k,v成对执行
    来打印其内容(avar)do print(k,v)end
    来查看

  • 默认情况下,
    avar
    bvar
    create
    变量是全局变量,其他模块将看到这些变量。大多数情况下,你宁愿让他们成为本地人

    local avar = -- ...
    local bvar = -- ...
    
    local function create (zebra)
      -- ...
    end
    
  • create函数显然需要一个表,因为它对其参数进行表索引(获取
    new
    键并调用它)。字符串没有“new”键,因此无法工作

  • 您并不是真正地动态调用模块。您正以常规方式需要该模块,而恰好您将模块返回值传递到了一个函数中

  • create
    始终返回
    nil
    ,因此执行
    print(create(avar))
    没有任何意义。您可能希望修改
    create
    以返回其对象,而不是打印它


您可以随时要求:

function create(zebraModuleName)
  zebraType = require(zebraModuleName)
  print(zebraType .new())
end

print(create("avar"))
print(create("bvar"))

您可以使用lua语言中的标准
require
,也可以使用元表/元方法构建自己的加载程序

1。创建全局函数:

function dynrequire (module)                                                                                           
  return setmetatable ({},{
    __index = function (table,key)
      return require(module..'.'..key)
    end
  })
end
2。创建对包可见的项目树。路径

./MySwiss/
  \___ init.lua
  \___ cut.lua
  \___ glue.lua
  \___ dosomething.lua
3。使您的模块动态化 您只需要在
MySwiss/init.lua
上放置这一行(就好像您在给一个PHP类命名一样):

4。需要您的模块并动态使用子属性 在脚本中,您只需要myswis和文件夹文件(或带有
dynrequire('myswis.SubFolderName')
的子文件夹)


请注意,MySwiss没有胶水键。但是当您尝试访问胶水键时,metamethod\uuu索引尝试要求子模块。您可以使用此技术创建完整的项目树。唯一的缺点是外部依赖项没有以这种方式打包。

感谢您所做的一切。我从整个程序中提取了这段代码,其中大部分功能n不在全局名称空间中。但是,我认为我的所有模块都不是本地的(根据您的第2点).问题:如何使模块成为本地模块?我应该在没有引号的情况下传递avar吗?根据第4点,我应该动态地要求吗?我只是在3个模块中的1个模块之间交替,所以我可以要求所有模块,但只想做正确的事情。谢谢帮助。@Kelly:尝试阅读Lua代码,而不是盲目地猜测该做什么。没有这样的问题作为本地模块的对象-可以是本地的或全局的对象是分配给模块表的值。(在本例中,
local avar=
vs
avar=
)。至于选择要使用的模块,您可以加载所有模块,并使用if-else-if或哈希表选择其中一个值,或者您可以传递一个带有要请求的模块名称的变量,而不是传递一个文本字符串。虽然要求所有内容都比较简单,但我会这样做,除非它最终证明是性能问题。谢谢!Th这正是我需要的。
./MySwiss/
  \___ init.lua
  \___ cut.lua
  \___ glue.lua
  \___ dosomething.lua
return dynrequire('MySwiss')
var X = require('MySwiss')
X.glue()