Taking the first example first: OCaml has structural typing of objects, not nominal typing. In other words, the type of an object is determined entirely by its methods (and their types). So the classes a
and b
are in fact the same type.
$ ocaml
OCaml version 4.00.0
# class a = object method get (x: a) = x end;;
class a : object method get : a -> a end
# class b = object inherit a method get (x: b) = x end;;
class b : object method get : a -> a end
# let a0 = new a;;
val a0 : a = <obj>
# let b0 = new b;;
val b0 : b = <obj>
# (a0: b);;
- : b = <obj>
# (a0: a);;
- : a = <obj>
# (b0: a);;
- : a = <obj>
# (b0: b);;
- : b = <obj>
#
(What I'm trying to show here is that both a0
and b0
are of type a
and of type b
.)
In the second example, I'd say you're trying to give a new type to the get
method. When you override a method in OCaml, the parameter and return types need to be the same as in the parent class.
The error message seems unfortunate. My guess is that the compiler is believing you that type b
is another name for type a
.
One of OCaml's strengths is that it will infer types. If you leave off the : b
for the parameter of get
in class b
, you get the following error instead:
This expression has type a. It has no method foo
This is a little more helpful, in that it shows (I think) that you're required to have type a
for the parameter.
Side comment (forgive me): if you come to the OO part of OCaml from a mainstream OO language, it might strike you as strange. But if you learn the FP part of OCaml first, you might wonder why all the mainstream OO languages get so many things wrong :-). (Granted, everything is tradeoffs and there is no one right way to structure computation. But OCaml's OO subsystem is doing something pretty impressive.)