15.2 The Basic Approach for Writing Modules
编写模块的基本方法The simplest way to create a module in Lua is really simple: we create a table, put all functions we want to export inside it, and return this table. Listing 15.2 illustrates this approach. Note how we define inv as a private name simply by declaring it local to the chunk.
Lua中创建模块的做简单方法确实简单:创建一个表,把所有要导出的函数放在其内,返回该表。清单15.2例示该方式。注意我们如何仅仅通过声明inv局部于程序块来把它定义为私有名字。
The use of tables for modules does not provide exactly the same functionality as provided by real modules. First, we must explicitly put the module name in every function definition. Second, a function that calls another function inside the same module must qualify the name of the called function. We can ameliorate these problems using a fixed local name for the module (M, for instance), and then assigning this local to the final name of the module. Following this guideline, we would write our previous module like this:
用表实现的模块不能提供同真的模块完全一样的功能。首先,我们必须在每个函数定义中显式地放入模块名。第二,调用同模块内的其他函数的函数必须限定被调用函数的名字。我们可用模块的固定的局部名字(例如M)改进这些问题,然后把该局部(变量)赋给模块的最终名字。我们遵循该原则这样来编写之前的模块:
local M = {}
complex = M -- module name 模块名
M.i = {r=0, i=1}
function M.new (r, i) return {r=r, i=i} end
function M.add (c1, c2)
return M.new(c1.r + c2.r, c1.i + c2.i)
end
Whenever a function calls another function inside the same module (or whenever it calls itself recursively), it still needs to prefix the name. At least, the connection between the two functions does not depend on the module name anymore. Moreover, there is only one place in the whole module where we write the module name. Actually, we can avoid writing the module name altogether, because require passes it as an argument to the module:
只要函数调用同模块的其他函数(或递归调用自己),它仍然需要前缀该名字。至少,两个函数之间的联系不再依赖模块名了。此外,我们只在整个模块中的一个地方写入模块名。实际上,我们能完全避免写入模块名,因为require把它作为参数传入模块:
local modname = ...
local M = {}
_G[modname] = M
M.i = {r=0, i=1}
----------------------- Page 6-----------------------142
Listing 15.2. A simple module:
清单15.2。简单的模块:
-----------------------------------------------------
complex = {}
function complex.new (r, i) return {r=r, i=i} end
-- defines a constant 'i' 定义常量'i'
complex.i = complex.new(0, 1)
function complex.add (c1, c2)
return complex.new(c1.r + c2.r, c1.i + c2.i)
end
function complex.sub (c1, c2)
return complex.new(c1.r - c2.r, c1.i - c2.i)
end
function complex.mul (c1, c2)
return complex.new(c1.r*c2.r - c1.i*c2.i,
c1.r*c2.i + c1.i*c2.r)
end
local function inv (c)
local n = c.r^2 + c.i^2
return complex.new(c.r/n, -c.i/n)
end
function complex.div (c1, c2)
return complex.mul(c1, inv(c2))
end
return complex
-----------------------------------------------------
With this change, all we have to do to rename a module is to rename the file that defines it.
通过这个改变,要给模块改名,我们要做的只是改变定义它的文件名。
Another small improvement relates to the closing return statement. It would be nice if we could concentrate all module-related setup tasks at the beginning of the module. One way of eliminating the need for the return statement is to assign the module table directly into package.loaded:
另一个小的改进涉及结尾的return语句。如果我们能把所有模块相关的配置任务集中在模块开始处会比较好。消除对return语句的需要的一个方法是把模块表直接赋到package.loaded中:
local modname = ...
local M = {}
_G[modname] = M
package.loaded[modname] = M
With this assignment, we do not need to return M at the end of the module: remember that, if a module does not return a value, require returns the current
----------------------- Page 7-----------------------143
value of package.loaded[modname].
通过该赋值,我们不需要在模块结尾返回M了:记住,如果模块不返回值,require返回package.loaded[modname]的当前值。
阅读(701) | 评论(0) | 转发(0) |