模块与包

 使用require加载模块

    一个规范的模块应该返回一个table作为这个模块所有导出功能的集合

    lua里没通过任何强制性语法规则要求创建模块时反回一个table

 但最好这么做,因为大多lua的模块都是这么发布的

--require的实现源代码

 function require(name)

 if not package.loaded[name] then

 local loader = findloader(name)

 if loader == nil then

 error("unable to load module "..name)

 end

 package.loaded[name] = true

 local res = loader(name)

 if res ~= nil then

 package.loaded[name] = res

 end

 end

 return package.loaded[name]

 end

    require的内部实现就是通过loadfile或loadlib来加载程序块

 所以加载模块就当相于把程序块看做一个函数

 然后使用模块的文件名作参数调用一次就加载完成了

    只要使用require加载过一次的模块就不会再重复加载了,除非手动把package.loaded[name]=nil

    已加载的模块记录在package.loaded的table里

    loader是一个加载器,它会从package.preload里找对应的加载函数来实施加载

    require"mod"会得到一个全局的mod变量

    local m = require"mod"可以重定义导入模块的名称

    require的加载路径如:

 ?;?.lua;c:\windows\?;/usr/local/lua/?/?.lua

 require会以模块名来替换所有"?",每个条目用";"隔开

 也就是说require只处理分号和问号

    require用于搜索lua文件的路径存放在变量package.path中

    当lua启动后便以环境变量LUA_PATH来初始化这个变量

    如果没有找到环境变量LUA_PATH就以编译时定义的一个默认常是值来初始化

    LUA_PATH里的";;"子串会替换成默认路径

    如果require找不到lua文件就会去找c程序库,路径放在package.cpath里用LUA_CPATH初始化

    在加载c程序库里如果模块名如a-b,则以b为模块加载

    如果一个模块名为mod.sub则认为sub是mod的子模块,在require时会使用配置好的分隔符替换"."

 如果mod.sub会替换为mod\sub这样就可以很容易的分目录放置了

 使用module创建模块

 手工写法

--创建模块--------------------------------------------------------------------------------      --require会把文件名当参数传进来,用这个变量记下来就行了

  local modname = ...

 

--创建一个local的table用于记录导出内容

     local _M = {}

 

--导出的table就等于这个local的table

     _G[modname] = _M

 

--有了这句就不用return _G[modname]给require了

     package.loaded[modname] = _M

 

--设置本环境继承全局环境,不然连接print都不能用,

     --其实如果在模块中要用全局内容,可能赋给local变量然后使用

     setmatetable(_M, {__index = _G})

 

--把这个local的table调成当前环境

     setfenv(1, _M)

 

--模块内容 ------------------------------------------------------------------------------         --由于使用了环境,所以local根本就不会进入环境,也就不会导出了

   local function test001()

   print("test001")

   end

 

--全局函数相当于_M.test002=function()end会导出

   function test002()

   print("test002")

   end

    内建module关键字

--这一句把上面创建模块部分的代码都包括了,没有package.seeall就不继承全局环境         module(...,package.seeall)