将一个单一的lua函数分解成多个小文件

我正在使用Lua和LÖVE创建一个游戏。

我更喜欢基于闭包的方法比面向对象编程,每个关卡都是包含运行游戏所需的所有局部和函数的函数的新实例。

我想将这个单一的函数拆分成多个文件。我的目前的解决方案类似于我在这里做的:将多个文件连接成一个文件 - 但我认为这还不够理想。

例如,我将使用从下面片段中的self.load函数的load.lua文件。

以下是参考巨大函数的代码片段:

levelSetup = function()
local time = 60
local timer = time
local timerIsRunning = true
local danger = 10
local handSize = 2
local itemsLeft = handSize
local curHand = 0
local lastHand = 10
local multiplier = 1
local self = {}

------------------------------------------------------
-- Initialize Values based on level Creation
------------------------------------------------------
self.load = function()
  if curLevel.time == 1 then
    time = 60
  elseif curLevel.time == 2 then
    time = 40
    multiplier = multiplier*1.5
  else
    time = 20
    multiplier = multiplier*2
  end

  if curLevel.danger == 1 then
    danger = 10 --low catastrophe chance
  elseif curLevel.danger == 2 then
    danger = 30 --medium chance
    multiplier = multiplier*1.5
  else
    danger = 50--high chance!
    multiplier = multiplier*2
  end

  if curLevel.handSize == 1 then
    handSize = 2
  elseif curLevel.handSize == 2 then
    handSize = 3
    multiplier = multiplier*1.5
  else
    handSize = 4
    multiplier = multiplier*2
  end
  itemsLeft = handSize
  timer = time
  self.nextHand()
end

  return self
end

最佳解决方案是什么?

点赞
用户1419918
用户1419918

将代码拆分成小文件

将代码拆分成更小的文件是一个好习惯,如果你这么做,一个优雅的解决方案(我个人的意见)是使用 return 语句。这是 Lua 生态系统中一个非常常见且优先考虑的实践方法

假设你的项目包含几个 子模块,分别为 submoduleA.lua_、_submoduleB.lua 和 _submoduleC.lua_。每个子模块都包含一些专业代码(可以是单个函数,也可以是一组函数,但让我们假设每个子模块中有一个单个函数)。

除了这些子模块之外,你还拥有一个 主文件(名为 _main.lua_),你希望从该文件中调用和使用在子模块中定义的函数。

submoduleA.lua 包含名为 funcA 的某个函数定义。这个函数可以有自己的本地变量,并使用参数,这没有问题。理想情况下,funcA 应该作为一个局部变量在 submoduleA.lua 文件中声明,以解决作用域问题。然后,在文件末尾,使用 return 语句返回函数本身。

-- 声明参数
local upvalue1 = ... -- 占位代码
local upvalue2 = ... -- 占位代码

-- 函数定义
local function funcA(arg1, arg2, ...)
  -- 一些代码
end

return funcA -- 结束文件

submoduleB.luasubmoduleC.lua 也一样。

然后,在 main.lua 文件中,你可以使用 require 语句轻松调用子模块中定义的函数。注意 require 的一个细节,你不需要添加扩展名 ".lua",因为它会自动添加扩展名(文档非常明确)。

local funcA = require ('submoduleA')
local funcB = require ('submoduleB')
local funcC = require ('submoduleC')

就是这样。再次强调,这是 Lua 中非常常见的模式。当我编写自己的项目/库时,尤其是当代码跨越几个文件时,我使用类似的技术。参考点是 JumperFloodFill

我还要推荐这些额外阅读材料,深入探讨了编写 Lua 模块时应采取的一些非常好的策略:

希望这篇文章对你有所帮助。

2014-05-28 07:57:41
用户3677376
用户3677376

一个函数必须在单个块中定义。然而,使用load函数,你可以使用多个来源来组装你的块数据。例如:

function closuredef( ... )
  local modules, n = { ... }, select( "#", ... )
  local index = -1
  local function reader()
    index = index + 1
    if index == 0 then -- chunk prefix
      return "local self = {};"
    elseif index == n+1 then -- chunk suffix
      return "\nreturn self"
    else -- read specified Lua files and add them to the chunk data
      local modname = modules[ index ]
      if modname ~= nil then
        local fname = assert( package.searchpath( modname, package.path ) )
        local file = assert( io.open( fname, "r" ) )
        local data = assert( file:read( "*a" ), "could not read '"..fname.."'" )
        file:close()
        return data
      end
    end
  end
  return assert( load( reader, "=closuredef" ) )
end

levelSetup = closuredef( "level.variables", "level.load" )

这个示例实现使用了 package.searchpath(这是 Lua 5.2 中的新功能)来使指定 Lua 文件更加方便。如果你仍然使用 Lua 5.1,则可以使用绝对文件名或者实现自己的package.searchpath函数。请参见 此处此处此处来查看样例。

不过,我不确定这是你的问题的最佳解决方案,例如你将会很难将错误消息中的行号映射到实际的错误位置...

2014-05-28 17:00:37