重写require使lua文件模块化

来源:互联网 发布:java 垃圾收集器 编辑:程序博客网 时间:2024/05/18 00:35
文件模块化目标
  • 没有声明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 = moduleRequireenduseModuleRequire()require("myMath")print(myMath.myadd(2,3))

运行useModuleRequire函数后,require就重定向为我们自己写的模块加载函数了。
require("myMath")就是加载myMath模块,myMath.myadd来访问模块的myadd函数。

-------------------------------------------------------------------------------------------------
--myMath.lua 这是模块代码示例
function myadd(a,b) return a+bendlocal function mydec(a,b) return a - bend_G.print("this is myMath end")



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

0 0
原创粉丝点击