我的几个模块包含具有两种方法的给定类类型的全局类实例, private_methodpublic_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  ;;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top