{ |one, step, back| }

The Shape Example in Icon

Contributed by Chris Rathman

Code for Icon

File: rectangle.icn

# define slots for Rectangle pseudo-class
record Rectangle(                      # constructor makeRectangle(x, y, width, height)
   draw,                               # procedure this.draw(this)
   moveTo,                             # procedure this.moveTo(this, x, y)
   rMoveTo,                            # procedure this.rMoveTo(this, deltax, deltay)
   getWidth,                           # procedure this.getWidth(this)
   getHeight,                          # procedure this.getHeight(this)
   setWidth,                           # procedure this.setWidth(this, width)
   setHeight,                          # procedure this.setHeight(this, height)
   x,                                  # attribute x
   y,                                  # attribute y
   width,                              # attribute width
   height)                             # attribute height

# Rectangle constructor
procedure makeRectangle(initx, inity, initwidth, initheight)
   return Rectangle(
      proc(rectangleDraw, 1),          # draw
      proc(rectangeMoveTo, 3),         # moveTo
      proc(rectangleRMoveTo, 3),       # rMoveTo
      proc(rectangleGetWidth, 1),      # getWidth
      proc(rectangleGetHeight, 1),     # getHeight
      proc(rectangleSetWidth, 2),      # setWidth
      proc(rectangleSetHeight, 2),     # setHeight
      initx,                           # x
      inity,                           # y
      initwidth,                       # width
      initheight);                     # height
end

# move the x & y position of the object
procedure rectangeMoveTo(this, newx, newy)
   this.x := newx;
   this.y := newy;
end
procedure rectangleRMoveTo(this, deltax, deltay)
   rectangeMoveTo(this, (this.x + deltax), (this.y + deltay));
end

# accessors for the width & height of the object
procedure rectangleGetWidth(this)
   return this.width;
end
procedure rectangleGetHeight(this)
   return this.height;
end
procedure rectangleSetWidth(this, newwidth)
   this.width := newwidth;
end
procedure rectangleSetHeight(this, newheight)
   this.height := newheight;
end

# draw the rectangle
procedure rectangleDraw(this)
   writes('Drawing a Rectangle at:(');
   writes(this.x);
   writes(',');
   writes(this.y);
   writes('), width ');
   writes(this.width);
   writes(', height ');
   write(this.height);
end

File: circle.icn

# define slots for Circle pseudo-class
record Circle(                         # constructor makeCircle(x, y, radius)
   draw,                               # procedure this.draw(this)
   moveTo,                             # procedure this.moveTo(this, x, y)
   rMoveTo,                            # procedure this.rMoveTo(this, deltax, deltay)
   getRadius,                          # procedure this.getRadius(this)
   setRadius,                          # procedure this.setRadius(this, radius)
   x,                                  # attribute x
   y,                                  # attribute y
   radius)                             # attribute radius

# Circle constructor
procedure makeCircle(initx, inity, initradius)
   return Circle(
      proc(circleDraw, 1),             # draw
      proc(circleMoveTo, 3),           # moveTo
      proc(circleRMoveTo, 3),          # rMoveTo
      proc(circleGetRadius, 1),        # getRadius
      proc(circleSetRadius, 2),        # setRadius
      initx,                           # x
      inity,                           # y
      initradius);                     # radius
end

# move the x & y position of the object
procedure circleMoveTo(this, newx, newy)
   this.x := newx;
   this.y := newy;
end
procedure circleRMoveTo(this, deltax, deltay)
   circleMoveTo(this, (this.x + deltax), (this.y + deltay));
end

# accessors for the radius of the object
procedure circleGetRadius(this)
   return this.radius;
end
procedure circleSetRadius(this, newradius)
   this.radius := newradius;
end

# draw the circle
procedure circleDraw(this)
   writes('Drawing a Circle at:(');
   writes(this.x);
   writes(',');
   writes(this.y);
   writes('), radius ');
   write(this.radius);
end

File: polymorph.icn

$include 'circle.icn'
$include 'rectangle.icn'

procedure main(args)
   # create a list containing various shape instances
   scribble := [makeRectangle(10, 20, 5, 6), makeCircle(15, 25, 8)];

   # iterate through the list and handle shapes polymorphically
   every ashape := !scribble do {
      ashape.draw(ashape);
      ashape.rMoveTo(ashape, 100, 100);
      ashape.draw(ashape);
   }

   # access a rectangle specific function
   rect := makeRectangle(0, 0, 15, 15);
   rect.setWidth(rect, 30);
   rect.draw(rect);
end

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