Sather

Contributed by Chris Rathman

Shape Type and Class (shape.sa)

-- abstract definition for type $SHAPE
abstract class $SHAPE is
   draw;
   moveto(newx:INT, newy:INT);
   rmoveto(dx:INT, dy:INT);
end;

-- shape class used for code inclusion
class SHAPE is
   private attr x:INT;
   private attr y:INT;

   moveto(newx:INT, newy:INT) is
      x := newx;
      y := newy;
   end;

   rmoveto(dx:INT, dy:INT) is
      x := x + dx;
      y := y + dy;
   end;
end;

Rectangle class (rectangle.sa)

class RECTANGLE < $SHAPE is
   include SHAPE;
   attr width:INT;
   attr height:INT;

   -- allocate the rectangle and initialize
   create(xVal:INT, yVal:INT, widthVal:INT, heightVal:INT):SAME is
      res:SAME := new;
      res.x := xVal;
      res.y := yVal;
      res.width := widthVal;
      res.height := heightVal;
      return res;
   end;

   -- draw the rectangle
   draw is
      #OUT + "Drawing a Rectangle at (";
      #OUT + x;
      #OUT + ",";
      #OUT + y;
      #OUT + "), radius ";
      #OUT + width;
      #OUT + ", height ";
      #OUT + height;
      #OUT + "\n";
   end;

   -- set the width of the rectangle
   setWidth(newWidth:INT) is
      width := newWidth;
   end;

   -- set the height of the rectangle
   setHeight(newHeight:INT) is
      height := newHeight;
   end;
end;

Circle Class (circle.sa)

class CIRCLE < $SHAPE is
   include SHAPE;
   attr radius:INT;

   -- allocate the circle and initialize
   create(xVal:INT, yVal:INT, radiusVal:INT):SAME is
      res:SAME := new;
      res.x := xVal;
      res.y := yVal;
      res.radius := radiusVal;
      return res;
   end;

   -- draw the circle
   draw is
      #OUT+"Drawing a Circle at (";
      #OUT+x+","+y;
      #OUT+"), radius "+radius+"\n";
   end;

   -- set the radius of the circle
   setRadius(newRadius:INT) is
      radius := newRadius;
   end;
end;

Class to try polymorphism (polymorph.sa)

class POLYMORPH is
   main is
      -- declare an $SHAPE array with length of 2
      aShape:ARRAY{$SHAPE} := #(2);

      -- set up some shape instances
      aShape[0] := #RECTANGLE(10, 20, 5, 6);
      aShape[1] := #CIRCLE(15, 25, 8);

      -- iterate through the shapes using element coroutine
      loop
         each:$SHAPE := aShape.elt!;
         each.draw;
         each.rmoveto(100, 100);
         each.draw;
      end;

      -- access a rectangle specific function
      aRectangle:RECTANGLE := #RECTANGLE(0, 0, 15, 15);
      aRectangle.setWidth(30);
      aRectangle.draw;
   end;
end;

Compiling

cs -main POLYMORPH -o polymorph shape.sa rectangle.sa circle.sa polymorph.sa

Output

Drawing a Rectangle at (10,20), radius 5, height 6
Drawing a Rectangle at (110,120), radius 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), radius 30, height 15

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