Frage

Einige meiner Module enthalten globale Klasseninstanzen, die einen bestimmten Klassentyp mit zwei Methoden, private_method und public_method implementieren.

Ich mag MyModule.my_instance # public_method von überall in meinem Programm zur Verfügung steht, und MyModule.my_instance # private_method nur innerhalb MyModule zur Verfügung.

Ich habe folgendes versucht:

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 

Dies führt jedoch zu einem Fehler:

Werte nicht übereinstimmen:

val my_instance : private_type

ist nicht in inbegriffen

val my_instance : public_type

I könnte schreiben Sie den Zwang manuell:

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 

Aber ich würde lieber nicht doppelt die Codegröße für etwas so einfaches wie diese.

Haben Sie Vorschläge, warum dies geschieht, und wie kann ich es umgehen?

War es hilfreich?

Lösung

Es gibt keine impliziten Nötigungen in ocaml. Vielleicht ist es wert Zwang in Funktors setzen (wenn Sie mehrere Module mit den gleichen Eigenschaften haben):

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)

Andere Tipps

Wahrscheinlich die beste Technik, um dies zu lösen, ist Privat Reihe zu verwenden Typen wie Garrigue beschrieben ( „private Zeilentypen: Abstrahieren die Unbenannt“, bitte schauen, wie ich nicht einen zweiten Link, um es veröffentlichen kann). Dies kann mit einem expliziten Objekttyp Ausdruck verwendet werden:

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

oder mit einem Objektpfad (das ist, was Sie benötigen):

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  ;;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top