集体实例类型的强制模块签名
题
我的几个模块包含具有两种方法的给定类类型的全局类实例, private_method
和 public_method
.
我想 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
但是,这导致错误:
值不匹配:
val my_instance : private_type
不包括在
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
但是,我宁愿不将代码大小加倍,因为这么简单。
您对为什么会发生这种情况以及如何解决它有任何建议吗?
解决方案
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)
其他提示
解决此问题的最佳技术可能是使用 私人行类型 如Garrigue所述(“私人行类型:抽象未命名”;请查找它,因为我无法发布第二个链接)。这可以与显式对象类型表达式一起使用:
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 ;;
不隶属于 StackOverflow