import與require的區別

載入一個模塊
import() 與 require() 功能相同,但具備必定程度的自動化特性。
假設咱們有以下的目錄結構:
~~~
app/
app/classes/
app/classes/MyClass.lua
app/classes/MyClassBase.lua
app/classes/data/Data1.lua
app/classes/data/Data2.lua
~~~
MyClass 中須要載入 MyClassBase 和 MyClassData。若是用 require(),MyClass 內的代碼以下:
local MyClassBase = require("app.classes.MyClassBase")
local MyClass = class("MyClass", MyClassBase)
local Data1 = require("app.classes.data.Data1")
local Data2 = require("app.classes.data.Data2")

假如咱們將 MyClass 及其相關文件換一個目錄存放,那麼就必須修改 MyClass 中的 require() 命令,不然將找不到模塊文件。
而使用 import(),咱們只須要以下寫:
local MyClassBase = import(".MyClassBase")
local MyClass = class("MyClass", MyClassBase)
local Data1 = import(".data.Data1")
local Data2 = import(".data.Data2")

當在模塊名前面有一個"." 時,import() 會從當前模塊所在目錄中查找其餘模塊。所以 MyClass 及其相關文件無論存放到什麼目錄裏,咱們都再也不須要修改 MyClass 中的 import() 命令。這在開發一些重複使用的功能組件時,會很是方便。
咱們能夠在模塊名前添加多個"." ,這樣 import() 會從更上層的目錄開始查找模塊。

不過 import() 只有在模塊級別調用(也就是沒有將 import() 寫在任何函數中)時,纔可以自動獲得當前模塊名。若是須要在函數中調用 import(),那麼就須要指定當前模塊名:
~~~ lua
# MyClass.lua
# 這裏的 ... 是隱藏參數,包含了當前模塊的名字,因此最好將這行代碼寫在模塊的第一行
local CURRENT_MODULE_NAME = ...
local function testLoad()
    local MyClassBase = import(".MyClassBase", CURRENT_MODULE_NAME)
    # 更多代碼
end
~~~


@param string moduleName 要載入的模塊的名字
@param [string currentModuleName] 當前模塊名
@return module

function import(moduleName, currentModuleName)
    local currentModuleNameParts
    local moduleFullName = moduleName
    local offset = 1


    while true do
        if string.byte(moduleName, offset) ~= 46 then -- .
            moduleFullName = string.sub(moduleName, offset)
            if currentModuleNameParts and #currentModuleNameParts > 0 then
                moduleFullName = table.concat(currentModuleNameParts, ".") .. "." .. moduleFullName
            end
            break
        end
        offset = offset + 1


        if not currentModuleNameParts then
            if not currentModuleName then
                local n,v = debug.getlocal(3, 1)
                currentModuleName = v
            end


            currentModuleNameParts = string.split(currentModuleName, ".")
        end
        table.remove(currentModuleNameParts, #currentModuleNameParts)
    end


    return require(moduleFullName)
endapp

相關文章
相關標籤/搜索