2011-11-23 55 views
5

推薦的方法是有辦法有有2+模塊遞歸地稱對方在Lua 5.2

  • 兩個Lua模塊(我們姑且稱之爲AB
  • 每個模塊使用功能,從其他,所以他們必須require彼此
  • 第三個模塊(我們稱之爲C)可以使用A而不是B例如

C.lua

local A = require 'A' 

-- ... 

A.foo() 
  • 可能有另一個模塊D需要B但不A和/或E同時需要AB
  • 既不A也不B也不其成員應添加到全局名稱空間。
  • 避免使用modulesetfenv功能(不建議使用在Lua 5.2)

相關Lua - how do I use one lib from another?(注:這個解決方案不能處理循環依賴)

回答

5

我發現了一個相當簡單的方法:

A.lua

local A = {} 
local B 

function A.foo() 
    B = B or require 'B' 
    return B.bar() 
end 

function A.baz() 
    return 42 
end 

return A 

B.lua

local B = {} 
local A 

function B.bar() 
    A = A or require 'A' 
    return A.baz() 
end 

return B 
+0

從這樣的函數內調用'require'有沒有什麼壞處?我只見過它在頂層使用。 – finnw

+4

[參考手冊](http://www.lua.org/manual/5.1/manual.html#pdf-require)中沒有關於它的警告,所以我認爲它是安全的。 –

+1

你可以在代碼中的任何地方使用'require'。例如,我經常使用這個習慣用法在文件中給定的點啓動RemDebug:'如果某些條件需要'remdebug.engine'.start()end' –

2

的標準方法在任何語言要做到這一點是引入調解員。然後模塊可以發佈和訂閱中介。 http://en.wikipedia.org/wiki/Mediator_pattern

在我的語言中有一個例子是mvccontrib總線,IEventAggregator和MVVM Lite Messenger類。他們都做同樣的事情。

3

的另一種方法,由歐文牧羊犬上the lua-l mailing list建議:

如果我們在每個模塊的頂部設置package.loaded[current-module-name],後來D任何其它模塊require可參考電流(可能不完整)模塊。

A.lua:

local A = {} 
package.loaded[...] = A 

local B = require 'B' 

function A.foo() 
    return B.bar() 
end 

function A.baz() 
    return 42 
end 

return A 

B.lua:

local B = {} 
package.loaded[...] = B 

local A = require 'A' 

function B.bar() 
    return A.baz() 
end 

return B 

這不會工作無處不在。例如,如果B的初始化取決於A.baz,那麼如果首先加載A,則它將失敗,因爲B將看到未完成版本的A,其中baz尚未定義。

+0

如果您不想調用需要整個時間(in每個函數都按[finnw'other solution](http://stackoverflow.com/a/8248862/1162609)所述),但似乎這是剩下的唯一方法。 Imho它也不錯,因爲模塊末尾的'return modename'被寫入'package.loaded [']'(無論如何使用這種不污染全局名稱空間和從模塊返回表的結構) –