Question

Plusieurs de mes modules contiennent des instances de classe mondiale qui mettent en œuvre un type de classe donnée avec deux méthodes, private_method et public_method.

Je veux MyModule.my_instance # public_method être disponible partout dans mon programme, et MyModule.my_instance # private_method d'être disponible que dans MyModule.

J'ai essayé ce qui suit:

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 

Cependant, cela se traduit par une erreur:

  

Les valeurs ne correspondent pas:

     

val my_instance : private_type

     

ne figure pas dans

     

val my_instance : public_type

peut écrire la contrainte manuellement:

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 

Mais je préfère ne pas doubler la taille du code pour quelque chose d'aussi simple que cela.

Avez-vous des suggestions sur pourquoi cela se produit, et comment je peux travailler autour d'elle?

Était-ce utile?

La solution

Il n'y a pas coercitions implicites dans OCaml. Peut-être qu'il vaut la peine de mettre la contrainte dans foncteur (si vous avez plusieurs modules avec ces mêmes propriétés):

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)

Autres conseils

Probablement la meilleure technique pour résoudre ce problème est d'utiliser ligne privée types comme décrit par Garrigue ( « types ligne privée: le Sans nom Extraire les », s'il vous plaît consulter en tant que je ne peux pas poster un second lien vers elle). Ceci peut être utilisé avec une expression explicite du type d'objet:

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

ou avec un chemin d'objet (qui est ce que vous avez besoin):

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  ;;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top