Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] does class polymorphism need to be so complicated?
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Chris Clearwater <chris@s...>
Subject: Re: [Caml-list] does class polymorphism need to be so complicated?
On Thu, Aug 21, 2003 at 10:29:46AM +0900, Jacques Garrigue wrote:
> Another approach which was not described yet, and which I use in
> lablgtk for instance, is to add a coercion method to classes which form
> the top of a hierarchy. This way you just have to write
>     printer#print obj#printable
> in place of a coercion, which may be shorter and avoid strange error
> messages when failing.
> To do this you just have to add the following to the printable virtual
> class:
>   class virtual printable = object (self)
>     method virtual ...
>     method printable = (self :> printable)
>   end

Another approach if you are using abstract base classes to simulate an
interface it to ditch the object system altogether and use closures.
You might do something like this:

printable.ml:

type printable = {
    print: unit -> unit;
}

let create p print = {
    print = fun () -> print p
}

let print p = p.print ()

circle.ml:

type circle = {radius: float}

let create r = {radius=r}
let print c = Printf.printf "Circle, radius: %f" c.radius
let as_printable c = Printable.create c print

main.ml:

let c = Circle.create 10.0
let p = Circle.as_printable c
let _ = Printable.print p

Some nice side effects of this is that you get better type inference,
non-virtual function calls when you dont need an abstract type
(Circle.print) and probally better performance for virtual calls as well.
Also keep in mind that for any virtual function that takes more
arguments besides the object itself (most of them) you can avoid the
unit hack and use partial application (say draw took a size and color
arguments):

drawable.ml:
type drawable = { draw: int -> color -> unit }
let create d draw = { draw = draw d }
let draw d = d.draw

 etc..
 main.ml somewhere:
 .. Drawable.draw c 10 red

> And if you're going to change the requirements of a method in the
> middle of your development, this means that there was something wrong
> in your design. Overall object-oriented languages are much weaker
> than functional languages at changing design afterwards.

With this method you just change the as_printable functions :)

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners