转载自http://mobile.51cto.com/iphone-285706.htm
LUA中关于Package定义学习笔记是本文要介绍的内容,主要是来学习lua中对Package,具体内容俩看本文详解。Package是个很逻辑的概念。也就是说很可能不是语言直接提供的设施。cpp里的namespace可以用来实现package,在LUA中则是依靠table机制来实现。实现的方式大同小异,本文总结了在《lua中文手册》中出现的3种方式。
方式一: 直接将所有组成包的数据和方法定义在包中,代码看起来像是这样:
- vector3d = {} -- 包名
- function vector3d.function1()
- ......
- end
- function vector3d.function2()
- ......
- if (vector3d.function1()) then
- ......
- end
- end
- return vector3d
这样定义的就是一个vector3d包,使用require语言打开这个包后,就可以使用 vector3d.function1和vector3d.function2这两个函数了。
这是最直接最好理解的一种Package定义方式,但是有一定的弊端。这个弊端主要体现在Package的实现过程中。可以看到,即使在
vector3d.function2()中使用function1()函数,也必须完整的加上vector3d包名,否则无法进行函数调用。Package的作者要稍微累一点,不过使用者倒是还好。特别的注意最后的 return vector3d 语句,有了这句后调用者可以按照如下方式重命名包:
- MyPackage = require "vector3d"
- MyPackage.function2()
方式二: 使用局部函数定义所有的Package内函数,然后在Package的结尾处将需要公开的函数直接放入Package中。代码看起来像这样:
- vector3d = {} -- 包名
- local function function1()
- ......
- end
-
- local function function2()
- ......
- if (function1()) then
- ......
- end
- end
- vector3d = {function1 = functoin1,
- function2function2 = function2
- }
- return vector3d
最后给包中赋值的部分就是将需要的接口公开的部分。这样做的好处:不需要公开的函数可以完全隐藏起来(都是local函数);Package内部的各个函数相互之间调用的时候不再需要加Package名称进行区分; 可以按照需要随意的重命名Package公开的接口名称。这种方式的弊端在于定义的时候需要写上local,这算不算弊端就看你了 - -。 就我个人而言,我还是比较喜欢这个定义方式。能明确的区分出接口和私有的定义,公开接口的名称还可以随意改变,这就意味着可以随意替换内部实现而不需要影响外部调用者。
无论用什么方法去定义Package,都是为了在逻辑上更好的规划代码层次。LUA中的table机制的确是一个活力无限的机制啊。Package依靠这个实现,LUA本身自己有些机制也依赖于Table(比如全局变量就放在_G表中)
手册里还有个如何"拆开"Package的代码段,很好的展现了table的强大之处(Package也是在table上构筑的逻辑产物)。将Package拆开的意思,就是将所有 Package中公开的名字放入_G表中。也就是让 Package.A() 变成_G.A (_G在一般情况下不需要写,默认引用了)
- function openpackage (ns)
- for n,v in pairs(ns)
- do
- _G[n] = v
- end
- end