2011-01-10 115 views
2

我的幾個模塊包含實現給定類類型有兩種方法,private_methodpublic_method全局類實例。模塊簽名Class實例類型強制

我想MyModule.my_instance # public_method可以在我的程序中的任何地方使用,MyModule.my_instance # private_method只能在MyModule內使用。

我已經嘗試以下操作:

class type public_type = object 
    method public_method : int 
end ;; 

class type private_type = object 
    method public_method : int 
    method private_method : int 
end ;; 

let make_private : unit -> private_type = fun() -> object 
    method public_method = 0 
    method private_method = 0 
end ;; 

module type MY_MODULE = sig 
    val my_instance : public_type 
end 

module MyModule : MY_MODULE = struct 
    let my_instance = make_private() 
    let _   = print_int (my_instance # private_method) 
end 

然而,這將導致一個錯誤:

Values do not match:

val my_instance : private_type

is not included in

val my_instance : public_type

可以寫手動脅迫:

module MyModule : MY_MODULE = struct 
    let my_instance = make_private() 
    let _   = print_int (my_instance # private_method) 

    let my_instance = (my_instance :> public_type) 
end 

但我'而不是將代碼大小加倍,以獲得簡單的答案這是。

你對爲什麼出現這種情況有什麼建議,我怎麼能解決呢?

回答

3

有OCaml中沒有隱含的強制。也許這是值得投入脅迫到仿函數(如果你有這些相同的性質幾個模塊):

module Hide(M:sig val my_instance : private_type end) : MY_MODULE = 
struct 
    let my_instance = (M.my_instance :> public_type) 
end 

module MyModule = Hide (struct 
    let my_instance = make_private() 
    let _   = print_int (my_instance # private_method) 
end) 
+0

我有點希望明確強迫MyModule中以MY_MODULE將作爲行爲,這可以用一個明確的對象類型的表達式中使用在... – 2011-01-10 16:16:33

3

可能解決這個是使用private row types由常綠矮灌木叢(「私人行類型中描述的最佳技術:抽象的未命名「;請查看它,因爲我無法發佈第二個鏈接)。

module type MY_MODULE2 = sig 
    type t = private < public_method : int; ..> 
    val my_instance : t 
end ;; 

module MyModule2 : MY_MODULE2 = struct 
    type t = private_type 
    let my_instance = make_private() 
    let _   = print_int (my_instance # private_method) 
end ;; 

或物體路徑(這是你需要什麼):

module type MY_MODULE3 = sig 
    type t = private #public_type 
    val my_instance : t 
end ;; 

module MyModule3 : MY_MODULE3 = struct 
    type t = private_type 
    let my_instance = make_private() 
    let _   = print_int (my_instance # private_method) 
end ;;