Contributed by Chris Rathman
Note: This one is on the ragged edge of demonstrating polymorphism. The technique used here does not provide for inheritance or method redefinition. The polymorphic dispatch is accomplished by doing an EVAL(string) type function within the virtual method. SNOBOL has some nice features with string handling and variable indirection, but the shape example really doesn't do much along these lines.
* Shape related methods - shared by all shape classes DEFINE('getX(this)') DEFINE('getY(this)') DEFINE('setX(this,newx)') DEFINE('setY(this,newy)') DEFINE('moveTo(this,newx,newy)') DEFINE('rMoveTo(this,deltax,deltay)') DEFINE('draw(this)') :(SHAPE_END) getX getX = x(this['fields']) :(RETURN) getY getY = y(this['fields']) :(RETURN) setX x(this['fields']) = newx :(RETURN) setY y(this['fields']) = newy :(RETURN) moveTo setX(this, newx) setY(this, newy) :(RETURN) rMoveTo moveTo(this, + getX(this) + deltax, + getY(this) + deltay) :(RETURN) draw APPLY(this['draw'], this) :(RETURN) SHAPE_END * Circle Class - (Note: the draw function is the only polymorphic function) DATA('Circle(x,y,radius)') DEFINE('makeCircle(x,y,radius)') DEFINE('getRadius(this)') DEFINE('setRadius(this,newradius)') DEFINE('drawCircle(this)') :(CIRCLE_END) makeCircle makeCircle = TABLE() makeCircle['fields'] = Circle(x, y, radius) makeCircle['draw'] = 'drawCircle' :(RETURN) getRadius getRadius = radius(this['fields']) :(RETURN) setRadius radius(this['fields']) = newradius :(RETURN) drawCircle OUTPUT = "Drawing a Circle at:(" + getY(this) "," getY(this) + "), radius " getRadius(this) :(RETURN) CIRCLE_END * Rectangle Class - (Note: the draw function is the only polymorphic function) DATA('Rectangle(x,y,width,height)') DEFINE('makeRectangle(x,y,width,height)') DEFINE('getWidth(this)') DEFINE('getHeight(this)') DEFINE('setWidth(this,newwidth)') DEFINE('setHeight(this,newheight)') DEFINE('drawRectangle(this)') :(RECTANGLE_END) makeRectangle makeRectangle = TABLE() makeRectangle['fields'] = Rectangle(x, y, width, height) makeRectangle['draw'] = 'drawRectangle' :(RETURN) getWidth getWidth = width(this['fields']) :(RETURN) getHeight getHeight = height(this['fields']) :(RETURN) setWidth width(this['fields']) = newwidth :(RETURN) setHeight height(this['fields']) = newheight :(RETURN) drawRectangle OUTPUT = "Drawing a Rectangle at:(" + getX(this) "," getY(this) + "), width " getWidth(this) + ", height " getHeight(this) :(RETURN) RECTANGLE_END * try shapes procedure START * create some shape instances scribble = ARRAY('2') scribble[1] = makeRectangle(10,20,5,6) scribble[2] = makeCircle(15,25,8) * iterate through the list and handle shapes polymorphically i = 1 LOOP each = scribble[i] :F(LOOP_END) draw(each) rMoveTo(each, 100, 100) draw(each) i = i + 1 :(LOOP) LOOP_END * call a rectangle specific function arect = makeRectangle(0,0,15,15) setWidth(arect, 30) draw(arect) END |
Drawing a Rectangle at:(10,20), width 5, height 6 Drawing a Rectangle at:(110,120), width 5, height 6 Drawing a Circle at:(25,25), radius 8 Drawing a Circle at:(125,125), radius 8 Drawing a Rectangle at:(0,0), width 30, height 15 |