Oz

Contributed by Chris Rathman

polymorph.oz

declare class Shape
   attr x y

   %% constructor
   meth init(Newx Newy)
      {self moveTo(Newx Newy)}
   end

   %% accessors for x & y
   meth setX(Newx) x <- Newx end
   meth setY(Newy) y <- Newy end
   meth getX(?$) @x end
   meth getY(?$) @y end

   %% move the x & y coordinates
   meth moveTo(Newx Newy)
      {self setX(Newx)}
      {self setY(Newy)}
   end
   meth rMoveTo(Deltax Deltay)
      {self moveTo({self getX($)} + Deltax {self getY($)} + Deltay)}
   end
end

declare class Rectangle from Shape
   attr width height

   %% constructor
   meth init(Newx Newy Newwidth Newheight)
      Shape, init(Newx Newy)
      {self setWidth(Newwidth)}
      {self setHeight(Newheight)}
   end

   %% accessors for the width & height
   meth setWidth(Newwidth) width <- Newwidth end
   meth setHeight(Newheight) height <- Newheight end
   meth getWidth(?$) @width end
   meth getHeight(?$) @height end

   %% draw the rectangle
   meth draw()
      {System.print 'Drawing a Rectangle at:('}
      {System.print {self getX($)}}
      {System.print ','}
      {System.print {self getY($)}}
      {System.print '), width '}
      {System.print {self getWidth($)}}
      {System.print ', height '}
      {Show {self getHeight($)}}
   end
end

declare class Circle from Shape
   attr radius

   %% constructor
   meth init(Newx Newy Newradius)
      Shape, init(Newx Newy)
      {self setRadius(Newradius)}
   end

   %% accessors for the radius
   meth setRadius(Newradius) radius <- Newradius end
   meth getRadius(?$) @radius end

   %% draw the circle
   meth draw()
      {System.print 'Drawing a Circle at:('}
      {System.print {self getX($)}}
      {System.print ','}
      {System.print {self getY($)}}
      {System.print '), radius '}
      {Show {self getRadius($)}}
   end
end

declare proc {TryMe}
   local Scribble Arect in
      %% create a list containing various shape instances
      Scribble = {New Rectangle init(10 20 5 6)} |
         {New Circle init(15 25 8)} | nil

      %% iterate through the list and handle shapes polymorphically
      {ForAll Scribble
         proc {$ Each}
            {Each draw()} in
               {Each rMoveTo(100 100)}
               {Each draw()}
         end
      }

      %% access a rectangle specific function
      Arect = {New Rectangle init(0 0 15 15)}
      {Arect setWidth(30)}
      {Arect draw()}
   end
end

{TryMe}

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