la contrainte par exemple la classe de type signature dans le module
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?
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 ;;