Oberon

Contributed by Chris Rathman

Shape class (Shape.Mod)

MODULE Shape;

   TYPE
      Shape* = POINTER TO ShapeDesc;
      ShapeDesc* = RECORD
         x: INTEGER;
         y: INTEGER;
      END;

   (* accessors for x & y *)
   PROCEDURE (self: Shape)getX*(): INTEGER;
   BEGIN
      RETURN self.x;
   END getX;

   PROCEDURE (self: Shape)getY*(): INTEGER;
   BEGIN
      RETURN self.y;
   END getY;

   PROCEDURE (self: Shape)setX(newx: INTEGER);
   BEGIN
      self.x := newx;
   END setX;

   PROCEDURE (self: Shape)setY(newy: INTEGER);
   BEGIN
      self.y := newy;
   END setY;

   (* move the shape position *)
   PROCEDURE (self: Shape)moveTo*(newx: INTEGER; newy: INTEGER);
   BEGIN
      self^.setX(newx);
      self^.setY(newy);
   END moveTo;

   PROCEDURE (self: Shape)rMoveTo*(deltax: INTEGER; deltay: INTEGER);
   BEGIN
      self^.moveTo(self^.getX() + deltax, self^.getY() + deltay);
   END rMoveTo;

   (* abstract draw method *)
   PROCEDURE (self: Shape)draw*();
   BEGIN
   END draw;

END Shape.

Rectangle class (Rectangle.Mod)

MODULE Rectangle;
   IMPORT Shape, Out;

   TYPE
      Rectangle* = POINTER TO RectangleDesc;
      RectangleDesc* = RECORD(Shape.ShapeDesc)
         width: INTEGER;
         height: INTEGER;
      END;

   (* accessors for width & height *)
   PROCEDURE (self: Rectangle)getWidth*(): INTEGER;
   BEGIN
      RETURN self.width;
   END getWidth;

   PROCEDURE (self: Rectangle)getHeight*(): INTEGER;
   BEGIN
      RETURN self.height;
   END getHeight;

   PROCEDURE (self: Rectangle)setWidth*(newwidth: INTEGER);
   BEGIN
      self.width := newwidth;
   END setWidth;

   PROCEDURE (self: Rectangle)setHeight*(newheight: INTEGER);
   BEGIN
      self.height := newheight;
   END setHeight;

   (* allocate and initialize a new object instance *)
   PROCEDURE Make*(x: INTEGER; y: INTEGER;
      width: INTEGER; height: INTEGER): Rectangle;
   VAR self: Rectangle;
   BEGIN
      NEW(self);
      self^.moveTo(x, y);
      self^.setWidth(width);
      self^.setHeight(height);
      RETURN self;
   END Make;

   (* draw the rectangle *)
   PROCEDURE (self: Rectangle)draw*();
   BEGIN
      Out.String("Drawing a Rectangle at:(");
      Out.Int(self^.getX(), 1);
      Out.String(",");
      Out.Int(self^.getY(), 1);
      Out.String("), width ");
      Out.Int(self^.getWidth(), 1);
      Out.String(", height ");
      Out.Int(self^.getHeight(), 1);
      Out.Ln;
   END draw;

END Rectangle.

Circle class (Circle.Mod)

MODULE Circle;
   IMPORT Shape, Out;

   TYPE
      Circle* = POINTER TO CircleDesc;
      CircleDesc* = RECORD(Shape.ShapeDesc)
         radius: INTEGER;
      END;

   (* accessors for radius *)
   PROCEDURE (self: Circle)getRadius*(): INTEGER;
   BEGIN
      RETURN self.radius;
   END getRadius;

   PROCEDURE (self: Circle)setRadius*(newradius: INTEGER);
   BEGIN
      self.radius := newradius;
   END setRadius;

   (* allocate and initialize a new object instance *)
   PROCEDURE Make*(x: INTEGER; y: INTEGER; radius: INTEGER): Circle;
   VAR self: Circle;
   BEGIN
      NEW(self);
      self^.moveTo(x, y);
      self^.setRadius(radius);
      RETURN self;
   END Make;

   (* draw the circle *)
   PROCEDURE (self: Circle)draw*();
   BEGIN
      Out.String("Drawing a Circle at:(");
      Out.Int(self^.getX(), 1);
      Out.String(",");
      Out.Int(self^.getY(), 1);
      Out.String("), radius ");
      Out.Int(self^.getRadius(), 1);
      Out.Ln;
   END draw;

END Circle.

Try shapes function (Polymorph.Mod)

MODULE Polymorph;
   IMPORT Shape, Circle, Rectangle;

   PROCEDURE Test*;

   VAR
      i: INTEGER;
      rect: Rectangle.Rectangle;
      circ: Circle.Circle;
      scribble: ARRAY 2 OF Shape.Shape;

   BEGIN
      (* set up some shape instances *)
      scribble[0] := Rectangle.Make(10, 20, 5, 6);
      scribble[1] := Circle.Make(15, 25, 8);

      (* iterate through some shapes and handle polymorphically *)
      FOR i := 0 TO 1 DO
         scribble[i]^.draw();
         scribble[i]^.rMoveTo(100, 100);
         scribble[i]^.draw();
      END;

      (* access a rectangle specific function *)
      NEW(rect);
      rect := Rectangle.Make(0, 0, 15, 15);
      rect^.setWidth(30);
      rect^.draw();
   END Test;

END Polymorph.

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 30, height 15

Chris Rathman / Chris.Rathman@tx.rr.com