Lua 基础教程(十四)模块
hudson 译 原文
什么是模块?
模块就像一个库,可以使用require加载,并有一个包含表的全局名称。模块可以由许多函数和变量组成。所有这些函数和变量都包装在表中,表充当命名空间。此外,行为良好的模块有必要的规定,根据需要可返回此表。
Lua模块的专长
在模块中使用表在许多方面非常有用,我们能够像操作任何其他Lua表一样操作模块。由于能够操作模块,因而能够提供其他语言需要特殊机制的额外功能。由于Lua中的这种自由模块机制,用户可以以多种方式调用Lua中的函数。其中一些如下所示。
-- Assuming we have a module printFormatter
-- Also printFormatter has a funtion simpleFormat(arg)
-- Method 1
require "printFormatter"
printFormatter.simpleFormat("test")
-- Method 2
local formatter = require "printFormatter"
formatter.simpleFormat("test")
-- Method 3
require "printFormatter"
local formatterFunction = printFormatter.simpleFormat
formatterFunction("test")
在上述示例代码中,可以看到Lua中的编程有多灵活,无需任何特殊的附加代码。
require函数
Lua提供了一个名为require的高级函数来加载所有必要的模块。它保持尽可能简单,
不需要模块提供有太多的信息就能够加载。require函数只是假设模块是定义一些值的代码块,这些值实际上是函数或者包含函数的表。
考虑下面一个简单的例子,一个模块有许多数学函数,称之为mymath,文件名是mymath.lua。文件内容如下:
local mymath = {}
function mymath.add(a,b)
print(a+b)
end
function mymath.sub(a,b)
print(a-b)
end
function mymath.mul(a,b)
print(a*b)
end
function mymath.div(a,b)
print(a/b)
end
return mymath
现在,要在另一个文件(例如moduletutorial.lua)中访问此Lua模块,需要使用以下代码片段:
mymathmodule = require("mymath")
mymathmodule.add(10,20)
mymathmodule.sub(30,20)
mymathmodule.mul(10,20)
mymathmodule.div(30,20)
为了运行此代码,我需要将两个Lua文件放在同一个目录中,或者,也可以将模块文件放在软件包路径中,后者需要额外的设置。
运行上述程序时,将得到以下输出:
30
10
200
1.5
几点注意事项
- 将模块和需要运行的文件都放在同一个目录中。
- 模块名称及其文件名应相同。
- 最佳实践是,
require函数返回模块 ,因此该模块最好如上所述方式实现,即使其他地方也可以找到其他类型的实现。
实现模块的旧方法
现在以旧的方式重写相同的示例,该示例使用package.seeall类型实现模块,是 Lua 5.1和5.0版本中使用的方法。 Mymath模块如下所示:
module("mymath", package.seeall)
function mymath.add(a,b)
print(a+b)
end
function mymath.sub(a,b)
print(a-b)
end
function mymath.mul(a,b)
print(a*b)
end
function mymath.div(a,b)
print(a/b)
end
Moduletutorial.lua中模块的使用情况如下所示:
require("mymath")
mymath.add(10,20)
mymath.sub(30,20)
mymath.mul(10,20)
mymath.div(30,20)
运行上述代码时, 会看到相同的输出。尽管如此,建议不要使用此方法实现模块,因为它不太安全。许多使用Lua进行编程的SDK(如Corona SDK)已弃用这种方法。