Класс экземпляра Тип принуждения в подписи модуля

StackOverflow https://stackoverflow.com/questions/4647063

Вопрос

Несколько моих модулей содержат экземпляры глобального класса, которые реализуют данный тип класса с двумя методами, private_method и public_method.

Я хочу MyModule.my_instance # public_method Быть доступным из любой точки моей программы и MyModule.my_instance # private_method быть доступным только внутри MyModule.

Я попытался следующее:

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 

Однако это приводит к ошибке:

Значения не совпадают:

val my_instance : private_type

не включен в

val my_instance : public_type

я мог Напишите принуждение вручную:

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 

Но я бы предпочел не удвоить размер кода для чего-то так просто, как это.

Есть ли у вас какие-либо предложения по тому, почему это происходит, и как я могу обойти его?

Это было полезно?

Решение

В Ocaml нет неявных принуждений. Может быть, стоит поставить принуждение в функтор (если у вас есть несколько модулей с этими же свойствами):

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)

Другие советы

Вероятно, лучшая техника для решения этого является использование Личные типы строк Как описано Garrigue («Частные типы строки: абстрагирование Безмятенных»; пожалуйста, посмотрите, как я не могу опубликовать вторую ссылку на него). Это может использоваться с явным выражением типов объекта:

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

или с пути объекта (который вы требуете):

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  ;;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top