{ |one, step, back| }

The Shape Example in Ocaml

Contributed by Chris Rathman

Code for Ocaml

File: polymorph.ml

class shape (initx:int) (inity:int) =
   object (self)
      val mutable x = initx
      val mutable y = inity

      (* get the x & y coordinates for the object *)
      method getX = x
      method getY = y

      (* set the x & y coordinates for the object *)
      method setX newx = x <- newx
      method setY newy = y <- newy

      (* move the x & y position of the object *)
      method moveTo newx newy =
         self#setX newx;
         self#setY newy
      method rMoveTo deltax deltay =
         self#setX (self#getX + deltax);
         self#setY (self#getY + deltay)

      (* draw method is effectively abstract *)
      method draw = ();
   end

class rectangle (initx:int) (inity:int) (initwidth:int) (initheight:int) =
   object (self)
      inherit shape initx inity
      val mutable width = initwidth
      val mutable height = initheight

      (* get the width & height of the object *)
      method getWidth = width
      method getHeight = height

      (* set the width & height of the object *)
      method setWidth newwidth = width <- newwidth
      method setHeight newheight = height <- newheight

      (* draw the rectangle *)
      method draw =
         print_string 'Drawing a Rectangle at:(';
            print_int self#getX;
            print_string ',';
            print_int self#getY;
            print_string '), width ';
            print_int self#getWidth;
            print_string ', height ';
            print_int self#getHeight;
            print_newline()
   end

class circle (initx:int) (inity:int) (initradius:int) =
   object (self)
      inherit shape initx inity
      val mutable radius = initradius

      (*  get the radius of the object *)
      method getRadius = radius

      (*  set the radius of the object *)
      method setRadius newradius = radius <- newradius

      (* draw the circle *)
      method draw =
         print_string 'Drawing a Circle at:(';
            print_int self#getX;
            print_string ',';
            print_int self#getY;
            print_string '), radius ';
            print_int self#getRadius;
            print_newline()
   end

(* recursive function to iterate through a list of shapes and draw *)
let rec drawloop lst =
   match lst with
     [] -> ()
   | head :: tail ->
      head#draw;
      head#rMoveTo 100 100;
      head#draw;
      drawloop tail;;

let main () =
   (* set up lists to hold the shapes *)
   let scribble1 = (new rectangle 10 20 5 6)::[] in
   let scribble2 = (new circle 15 25 8)::[] in

   (* iterate through the lists and handle shapes polymorphically *)
   drawloop scribble1;
   drawloop scribble2;

   (* call a rectangle specific instance *)
   let arectangle = new rectangle 0 0 15 15 in
   arectangle#draw;
   arectangle#setWidth 30;
   arectangle#draw;;

main ();;

Note: Compiling the code

 ocamlc -c polymorph.ml
     ocamlc -o polymorph.exe polymorph.cmo

Output

Drawing a Rectangle at:(10,20), width 5, height 6
Drawing a Rectangle at:(110,120), width 5, height 6
Drawing a Circle at:(15,25), radius 8
Drawing a Circle at:(115,125), radius 8
Drawing a Rectangle at:(0,0), width 15, height 15
Drawing a Rectangle at:(0,0), width 30, height 15