重写require使lua文件模块化

时间:2014-02-21 15:06:22   收藏:0   阅读:434
文件模块化目标
  • 没有声明local的变量不会加入到全局变量,而是作为模块的变量
  • 访问模块变量一律使用 "模块名.变量名"的形式
  • 模块中使用显示的方式访问全局变量
  • 模块是只读的,外部不能修改(能不能修改,可以在加载时设置)

实现思路:
  • 为了杜绝把不写local的变量从全局改为模块,我们需要为模块设置单独的环境
  • 在模块中访问全局变量有两种方式:
    1.     隐式访问:设置环境的元表 setmetable(env,{--index = _G}) , 但是隐式访问会带来一定的问题,其他模块可以通过该模块访问全局变量,不明真相的人会认为该变量或函数式属于该模块。所以尽量不采用这种方式。
    2.     显示访问 :  环境中设置成员_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")



转载请注明出处:重写require使lua文件模块化

原文:http://blog.csdn.net/oracleot/article/details/19575401

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!