types - 使用显式类型将对象中的方法的可见性限制为定义它的模块

标签 types ocaml

我在 OCaml 中有一个坐标“类”(使用返回对象文字的工厂函数实现),我试图弄清楚如何将该对象上的方法的可见性限制在它定义的模块中。

这是源文件

(* coordinate.ml *)
type coordinate = < get_x : int; get_y : int >

let create_coord ~x ~y = object
  val x = x
  val y = y
  method get_x = x
  method get_y = y
  (* hide this method from public interface *)
  method debug_print = Printf.printf "(x=%d, y=%d)\n"
end

这是界面

(* coordinate.mli *)
(* the type synonym coordinate is compatible with the "real"
 * type, but does not expose the debug_print method *)
type coordinate = < get_x : int; get_y : int >

val create_coord : x:int -> y:int -> coordinate

我的意图是让 create_coord 返回的对象在 Coordinate 模块的主体内显示所有方法。 coordinate 类型别名在 .ml 文件中重复的唯一原因是为了满足编译器/允许它在 .mli 中使用.

但是,我想阻止此模块的使用者使用 debug_print 方法。我认为,“由于 OCaml 支持结构类型”,就类型归属而言,具有严格较少方法的对象类型将是“兼容”类型。

但是,当我尝试编译文件时出现以下错误:

$ ocamlc coordinate.mli
$ ocamlc coordinate.ml
File "coordinate.ml", line 1:
Error: The implementation coordinate.ml
       does not match the interface coordinate.cmi:
       Values do not match:
         val create_coord :
           x:'a ->
           y:'b ->
           < debug_print : int -> int -> unit; get_x : 'a; get_y : 'b >
       is not included in
         val create_coord : x:int -> y:int -> coordinate
       File "coordinate.ml", line 3, characters 4-16: Actual declaration
Exit 2

有没有办法限制 debug_printCoordinate 之外的可见性,同时使其在内部可以自由访问?

最佳答案

我认为最好的解决方案是使用私有(private)行类型:

module M : sig
  type t = private < x : int; y : int; .. >
  val make : int -> int -> t
  val f: t -> unit
end = struct
  type t = < x : int; y : int; z : [`Not_exposed] >

  let make x y = object
    method x = x
    method y = y
    method z = `Not_exposed
  end

  let f o =
    (* Access a method not exposed outside of the module *)
    assert (o#z = `Not_exposed)
end;;

这样,您不需要任何强制功能。尽管如此,任何类型 t 的对象都可以在模块 M 中看到其私有(private)方法,但只有公共(public)方法(xy)可以外部访问。在 manual 中查找更多信息.

关于types - 使用显式类型将对象中的方法的可见性限制为定义它的模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47314755/

相关文章:

mysql - PostgreSQL 中 varchar 类型的等价物是什么?

OCaml : add element to a list inside an Array

c - 为什么这个 OCaml 程序比我的 C 程序快?

java - 术语非原始类型和对象类型有什么区别?

c++ - 地址是什么数据类型?

c# - 从类型创建通用变量 - 如何?或者将 Activator.CreateInstance() 与属性 { } 而不是参数 ( ) 一起使用?

polymorphism - 为什么 `ref None` 值在 Ocaml 中受到限制?

go - 如何在不知道值类型的情况下访问 map 的键?

scala - Haskell、Scala、Clojure,如何选择高性能模式匹配和并发

ocaml - 如何在 OCaml 中定义 int64?