重写require使lua文件模块化
时间:2014-02-21 15:06:22
收藏:0
阅读:434
文件模块化目标:
- 没有声明local的变量不会加入到全局变量,而是作为模块的变量
- 访问模块变量一律使用 "模块名.变量名"的形式
- 模块中使用显示的方式访问全局变量
- 模块是只读的,外部不能修改(能不能修改,可以在加载时设置)
实现思路:
- 为了杜绝把不写local的变量从全局改为模块,我们需要为模块设置单独的环境
- 在模块中访问全局变量有两种方式:
- 隐式访问:设置环境的元表 setmetable(env,{--index = _G}) , 但是隐式访问会带来一定的问题,其他模块可以通过该模块访问全局变量,不明真相的人会认为该变量或函数式属于该模块。所以尽量不采用这种方式。
- 显示访问 : 环境中设置成员_G , env = { _G = _G } , 在模块中访问全局变量需要使用 _G.xxxx的形式
- 可以通过元表的形式把模块设为只读
- 为了不在每个模块文件中添加代码,只能通过重写require函数的方式实现。
实现代码如下:
--------------------------------------------------------------------------------------------------
--main.lua
local function useModuleRequire() -- function readOnly(t) local proxy = {} local mt = { __index = t, __newindex = function(t, k, v) error("our moduleRequire forbid update a read-only module", 2) end } setmetatable(proxy, mt) return proxy end function readOnly2(t) local mt = { __newindex = function(t, k, v) error("our moduleRequire forbid update a read-only module", 2) end } setmetatable(t, mt) return t end --模块化的require,name是模块名,bReadOnly模块设置为是否只读 local function moduleRequire(name,bReadOnly) if not package.loaded[name] then local loader = loadfile if loader == nil then error("unable to load module "..name) end package.loaded[name] = true local loadRes = loader(name..".lua") local env = {_G = _G,} --引入全局表的环境 通过_G.xxxx形式访问全局变量 local loadResWithEnv = setfenv(loadRes,env) --设置环境,让加载的文件模块化 local res = loadResWithEnv() local env2 = env if bReadOnly == nil then bReadOnly = true end if bReadOnly then env2 = readOnly2(env) else env2 = env end _G[name] = env2 --把模块变成只读 if res ~= nil then package.loaded[name] = res end end return package.loaded[name] end _G.originalRequire = _G.require _G.require = moduleRequire end useModuleRequire() require("myMath") print(myMath.myadd(2,3))
运行useModuleRequire函数后,require就重定向为我们自己写的模块加载函数了。
require("myMath")就是加载myMath模块,myMath.myadd来访问模块的myadd函数。
-------------------------------------------------------------------------------------------------
--myMath.lua 这是模块代码示例
function myadd(a,b) return a+b end local function mydec(a,b) return a - b end _G.print("this is myMath end")
原文:http://blog.csdn.net/oracleot/article/details/19575401
评论(0)