Me gustaría entender el motivo de este comportamiento de los objetos OCAML. Supongamos que tengo una clase A
que llama a métodos de un objeto de otra clase B
. Esquemáticamente, A # f llama a B # g y B # h. La práctica normal en OOP es que me gustaría evitar el uso de B como una clase concreta fija, sino que declaro solo una interfaz para B. ¿Cuál es la mejor manera de hacer esto en OCAML? Probé varias opciones y no entiendo muy bien por qué algunas funcionan, mientras que otras no. Aquí están los ejemplos del código.¿Por qué las variables de tipo no enlazadas en el objeto OCAML no aparecen cuando se utiliza el tipo de clase?
Versión 1:
# class classA = object
method f b = b#g + b#h
end ;;
Error: Some type variables are unbound in this type:
class a : object method f : < g : int; h : int; .. > -> int end
The method f has type (< g : int; h : int; .. > as 'a) -> int where 'a
is unbound
Este comportamiento es bien conocido: ocaml infiere correctamente que b
tiene el objeto abierto tipo <g:int;h:int;..>
pero luego se queja de que mi clase no declara ningún tipo de variables. Por lo tanto, parece que classA
es requiere para tener variables de tipo; Luego introduje una variable de tipo explícitamente.
Versión 2:
# class ['a] classA2 = object
method f (b:'a) = b#g + b#h
end ;;
class ['a] classA2 :
object constraint 'a = < g : int; h : int; .. > method f : 'a -> int end
Esto funciona, pero la clase ahora es explícitamente polimórfico con una restricción de tipo, como muestra ocaml. También es confuso que el tipo de clase contiene una variable de tipo 'a
, y todavía puedo decir let x = new classA2
sin especificar un valor de tipo para 'a
. ¿Por qué es eso posible?
Otro inconveniente de classA2
es que una restricción de tipo explícita (b:'a)
contiene una variable de tipo. Después de todo, sé que b
debe ajustarse a una interfaz fija en lugar de a un tipo desconocido 'a
. Quiero que OCAML verifique que esta interfaz sea correcta.
Así que en la versión 3 que primero declaró una interfaz classB
como un tipo de clase y luego declaró que b
debe ser de este tipo:
# class type classB = object method g:int method h:int end;;
class type classB = object method g : int method h : int end
# class classA3 = object method f (b:classB) = b#g + b#h end;;
class classA3 : object method f : classB -> int end
Esto funciona también, pero mi perplejidad sigue siendo: ¿por qué no classA3
requiere polimorfismo explícito más?
Resumen de preguntas:
- ¿Por qué es posible utilizar
new classA2
sin especificar un tipo para'a
a pesar de queclassA2
se declara con un tipo de variable'a
? - ¿Por qué
classA3
acepta una restricción de tipo(b:classB)
y ya no requiere una variable de tipo enlazado? - ¿Es la funcionalidad de
classA2
yclassA3
diferente de alguna manera sutil, y si es así, cómo?
¡Cosas geniales, gracias! Entonces la clase A siempre necesita tener polimorfismo, solo que a veces no se muestra explícitamente. Además, parece que OOP requiere coacciones explícitas o variables de tipo explícitamente cuantificadas universalmente para los métodos, que son adiciones relativamente recientes a OCAML. – winitzki