Pregunta

Varios de mis módulos contienen instancias de clase mundial que implementan un tipo de clase dada con dos métodos, private_method y public_method.

Quiero MyModule.my_instance # public_method esté disponible desde cualquier lugar en mi programa, y ??MyModule.my_instance # private_method a estar disponible sólo dentro de MyModule.

He intentado lo siguiente:

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 

Sin embargo, esto resulta en un error:

Los valores no coinciden:

val my_instance : private_type

no está incluido en

val my_instance : public_type

podría escribir la coerción manualmente:

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 

Pero prefiero no duplicar el tamaño del código para algo tan simple como esto.

¿Tiene alguna sugerencia sobre qué sucede esto, y cómo puede trabajar alrededor de ella?

¿Fue útil?

Solución

No hay coacciones implícitas en ocaml. Tal vez vale la pena poner en la coacción funtor (si dispone de varios módulos con estas mismas propiedades):

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)

Otros consejos

Probablemente la mejor técnica para resolver esto es utilizar fila privada tipos según lo descrito por Garrigue ( "tipos de fila privadas: abstracción de los sin nombre", por favor, ven hacia arriba ya que no puedo publicar un segundo enlace a ella). Esto se puede utilizar con una expresión tipo de objeto explícito:

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  ;;

o con una ruta de objeto (que es lo que necesita):

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  ;;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top