Приведение типа экземпляра класса в сигнатуре модуля - PullRequest
2 голосов
/ 10 января 2011

Некоторые из моих модулей содержат экземпляры глобального класса, которые реализуют данный тип класса с помощью двух методов, 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 

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

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

Ответы [ 2 ]

3 голосов
/ 28 января 2011

Вероятно, лучший метод для решения этой проблемы - использовать частные типы строк , как описано в 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  ;;
3 голосов
/ 10 января 2011

Нет явных принуждений в 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)
...