2013-02-12 94 views
4

假設我們正在使用面向對象的語言,並且有兩個類X和Y,並且這些類之間存在雙向關係。將面向對象的模型映射到Clojure

所以X的一個實例可以指向Y的一個實例,反之亦然。

在Clojure中類通常翻譯成地圖,所以我們可以有:

{:type :x :name "instance of X"} 
{:type :y :name "instance of Y"} 

我們如何代表這些「物」之間的雙向關係,而無需使用類似「外鍵」?或者這通常是直接委託給數據庫的東西?

回答

4

在Clojure中查看對應於面嚮對象語言中的分層對象樹的深嵌套地圖很常見,例如,

{:type :x 
:name "instance of X" 
:y {:type :y 
    :name "instance of Y"}} 

事實上,這是很常見的,clojure.core提供像get-inassoc-in,並update-in核心功能,以促進與這種結構的工作。

當然,當被建模的對象之間存在自然的層次關係或所有權關係時,這最有效。在循環引用的情況下,該結構會崩潰(假設您堅持使用持久數據結構) - 爲了明白爲什麼,嘗試構建一個包含自身作爲值的Clojure映射。

我通常看到的這種方式處理的是介紹使用​​一個間接的層:

(def x {:type :x, :name "x instance", :y (atom nil)}) 
(def y {:type :y, :name "y instance", :x (atom nil)}) 
(set! *print-level* 3) ;; do this in the REPL to avoid stack overflow 
         ;; when printing the results of the following calls 
(reset! (:y x) y) 
(reset! (:x y) x) 
+0

不會裁判更適合於這一點,因爲他們的變化可以協調? – 2013-02-12 21:11:25

+0

順便說一句,這段代碼在我嘗試時導致「StackOverflowError clojure.lang.RT.toArray(RT.java:1544)」 – 2013-02-12 21:12:48

+0

取決於應用程序。如果你只是想在地圖創建時設置一次值,原子可能就足夠了。如果你要做大量的更新,並希望確保圖的一致性,那麼是的,你應該使用refs。堆棧溢出可能來自打印結果,因爲打印原子會顯示其值 - 不確定是否* print-level *'會影響該值。 – Alex 2013-02-12 21:16:14