module函數

模塊的基本編寫方法

local M = {}
local modname = 'a'
_G[modname] = M
package.loaded[modname] = M

function M.play()
    print('play')
end

function M.say()
    print('say')
    M.play()
end

return M

這裏的問題是模塊內函數之間的調用仍然要保留模塊名的限定符,好比say中調用play方法就須要M.play。函數

使用環境

解決上面那個問題能夠用setfenv把當前模塊的全局環境設置爲M,因而,定義函數的時候就不用加上M,模塊中函數間的調用也不須要加M限定。lua

local M = {}
local modname = 'a'
_G[modname] = M
package.loaded[modname] = M
setfenv(1, M)

function play()
    -- print('play')
end

function say()
    -- print('say')
    play()
end

return M

上面把print註釋掉了,是由於這個時候調用play或者say方法會報錯,大概是說沒有print這個東西。由於當前的全局環境變了,不是_G而是M,M中固然沒有print。那要如何使用到_G中的全局變量呢?元表。code

local M = {}
local modname = 'a'
_G[modname] = M
package.loaded[modname] = M

setmetatable(M, {__index = _G})
setfenv(1, M)

使用module

能夠使用module函數來替換下面的代碼io

local M = {}
local modname = 'a'
_G[modname] = M
package.loaded[modname] = M

setfenv(1, M)

上面的能夠簡化爲table

module('a')

module默認是不提供外部訪問的,也就是說這個時候print這些仍是不能用的。function

若是要加上setmetatable(M, {__index = _G})的效果,須要加上package.seeall參數,如class

module('a', package.seeall)

稍微一個總結:使用module來建立模塊,定義函數以及模塊內函數間的調用均可以不用加上限定附,好比上面的M。還有就是能夠不用寫return M,以及能夠訪問到_G中的全局變量。變量

附:module

setfenv(f, table):設置一個函數的環境meta

  (1)當第一個參數爲一個函數時,表示設置該函數的環境

  (2)當第一個參數爲一個數字時,爲1表明當前函數,2表明調用本身的函數,3表明調用本身的函數的函數,以此類推

  所謂函數的環境,其實一個環境就是一個表,該函數被限定爲只能訪問該表中的域,或在函數體內本身定義的變量。

相關文章
相關標籤/搜索