English version
Accueil     À propos     Téléchargement     Ressources     Contactez-nous    

Ce site est rarement mis à jour. Pour les informations les plus récentes, rendez-vous sur le nouveau site OCaml à l'adresse ocaml.org.

Browse thread
Class/prototype-based OO
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: 2006-08-25 (11:31)
From: skaller <skaller@u...>
Subject: Re: [Caml-list] Class/prototype-based OO
On Fri, 2006-08-25 at 09:51 +0200, David Baelde wrote:
> Hi list,
> After having had to learn Java, I was annoyed by the lack of subtyping
> compared to OCaml. In Java two identical classes with different names
> cannot be used identically. I then re-read Wikipedia's articles on
> prototype-based [1] and class-based [2] OO. I used to be convinced
> that OCaml was cited in the first category. It is not the case, and I
> see now that the question is not trivial.
> It is said that prototype-based OO is criticized for being too
> dynamic, I believe that OCaml style of OO is an example of static
> language having at least the most interesting features of
> prototype-based OO.
> Any opinion?

Yeah, you're confused. Ocaml isn't using prototypes.

Languages like Cecil use prototypes. In this case,
you create an object at run time, and make similar
objects by cloning the original object.

This is entirely unrelated to the difference between
classes with nominal (named) typing (C++, Java)
and classes with structural typing (Ocaml).
There is no doubt whatsoever nominal typing is rubbish :)

The reason, trivially, is that any structurally based
typing can always be promoted to a nominally typed
system by simply adding a phantom nominal type
representing the 'name'.

On the other hand, structural typing solves a major
problem with nominal typing which destroys class based
object orientation entirely: the inability to devise
new algorithms which use objects satisfying certain
axioms -- in other words, an abstraction -- unless the
class was derived from, or specified to implement,
that particular abstraction when it was designed:

	class X : public Abstraction { ..

in C++.

The number of possible interfaces a given class may have
is combinatorial in the number of methods, and so it
is not tenable to name them all in advance, but if you
want to use one NOT named previously, after creating
it you have to invade every instance class specification
and add a new interface to its base-class or implements list,
breaking the open/closed principle on which dynamic dispatch
and the very notion of encapsulation central to OO actually

	class X : public Abstraction, public NewAbstraction {
	//                          ^^^^^^^^^^^^^^^^^^^^^^^^
	// violation of encapsulation!

Thus, from a software engineering viewpoint, nominal typing
is not a viable option .. which is one reason programming
in Java or C++ using OO sucks.

In Ocaml, it works much better because you can actually
write algorithms which work with many different types,
provided only they support the 'right methods'.

You should note structural typing does NOT solve the
problem, but it does reduce the problem. It doesn't
solve the problem, because methods have names which
count in the class signature. It's the old problem
all over again, but at a lower level.

And even if this weren't so it STILL wouldn't solve
the problem, because more than one data type can
represent the same thing .. so even the types may
be semantically, but not physically, equivalent:

	int * float // a pair of an int and a float
	float * int // woops, ANOTHER type, same information!

In ALL these cases *including* the nominal typing situation
there is a universal solution: wrapping/proxies/forwarding
functions/delegation/mapping as you want to call it, in which
you build the required interface, and implement its methods
by dispatching to an object of the 'wrong' type.

However this is not only messy .. particularly in C++
since it has no garbage collection .. it also tends to 
destroy subtyping.

There is a point where all this housekeeping is so unreliable
and difficult you'd be better off with dynamic typing,
such as that provided by prototype based OO, or other
kinds of object systems such as that used by Python
(which is more or less prototype based but actually
uses classes rather than cloning prototypes).

The boundary is probably close to the amazing feat of
constructing an Ocaml binding for GTK.

John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net