Contributed by Chris Rathman
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. |
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. |
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. |
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. |
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 |