Nice TWiki > Doc > CodeExamples > VisitorPatternMultiMethodExample > ExtensibleVisitorPatternExample TWiki webs:
Dev | Doc | Main | TWiki | Sandbox
Doc . { Changes | Index | Search | Go }
/* Please try the NoviceExamples before the MultiMethodExamples
To compile:
   nicec --sourcepath .. -a extensible.jar extensible
To run:
   java -jar extensible.jar
*/


// Extensible Visitor Pattern: Types
//----------------------------------

abstract class Shape {
   <T> T process(IShapeVisitor<T> v);
}

class Square extends Shape { 
   double side; 
   
   process(IShapeVisitor v) = v.forSquare(this);
}

class Circle extends Shape { 
   double radius; 
   
   process(IShapeVisitor v) = v.forCircle(this);
}

class Translated extends Shape { 
   Point d; 
   Shape shape; 

   
   process(IShapeVisitor v) = v.forTranslated(this);
}

class Point { double x; double y; }


// Extensible Visitor Pattern: Operations
//---------------------------------------

interface IShapeVisitor<T> {
   T forSquare(Square s);   
   T forCircle(Circle s);   
   T forTranslated(Translated s);     
}

<T| boolean <: T <: boolean>
class ContainsPointVisitor<T> implements IShapeVisitor<T> {
   Point point; 
   
   ContainsPointVisitor<T> makeVisitor(Point newp) =
      new ContainsPointVisitor(point: newp);

   forSquare(Square s){     
      let d = s.side/2;
      return 
         (point.x >= -d && point.x < d) && 
         (point.y >= -d && point.y < d);
   }


   forCircle(Circle s) =
      // just test the bounding box     
      (point.x >= -s.radius && point.x < s.radius) && 
      (point.y >= -s.radius && point.y < s.radius);
   

   forTranslated(Translated s){ 
      let p' = 
         new Point(
            x: point.x - s.d.x,
            y: point.y - s.d.y );
 
      return s.shape.process(this.makeVisitor(p'));
   }
}  



/*
   =================================================
   Can we add a type and operation without modifying 
   the original code?
   ================================================= 
*/


// Extensible Visitor Pattern: Adding Type Variants
//-------------------------------------------------

class Union extends Shape {
   Shape shape1; 
   Shape shape2; 

   process(IShapeVisitor v) = cast(v).forUnion(this);
}

interface IUnionVisitor<T> extends IShapeVisitor<T> {
   T forUnion(Union s);  
}

<T| boolean <: T <: boolean>
class ContainsPointUnionVisitor<T> 
extends ContainsPointVisitor<T> implements IUnionVisitor<T> {

   ContainsPointUnionVisitor<T> 
   makeVisitor(Point newp) =
      new ContainsPointUnionVisitor(point: newp);

   forUnion(Union s) = 
      s.shape1.process(this) || s.shape2.process(this);
}


// Extensible Visitor Pattern: Adding Operations
//----------------------------------------------

<T| Shape <: T <: Shape>
class ShrinkVisitor<T> implements IUnionVisitor<T> {
   double toPercent;

   forSquare(Square s) = 
      new Square(side: (s.side*toPercent)/100);
      
   forCircle(Circle s) = 
      new Circle(radius: (s.radius*toPercent)/100); 
  
   forTranslated(Translated s) = 
      new Translated(
         d: s.d, 
         shape: s.shape.process(this)
      );  
      
   forUnion(Union s) = 
      new Union(
         shape1: s.shape1.process(this), 
         shape2: s.shape2.process(this)
      );     
}


// Visitor Pattern: Testing
//---------------------------

void main(String[] args){
   let s = new Square(side: 4);
   let c = new Circle(radius: 2);

   let t = 
      new Translated(
         d: new Point(x: 1.5, y: 0),  
         shape: c 
         );

   let p = new Point(x: 3, y: 0);
   let v = new ContainsPointUnionVisitor(point: p);

   println("square contains point " + s.process(v));
   println("circle contains point " + c.process(v));
   println("translated contains point " + t.process(v));

   let vshrink = new ShrinkVisitor(toPercent: 50);
   let t' = t.process(vshrink); 
   println("shrunk translated contains point " + t'.process(v));
                            
   let u = new Union(shape1: s, shape2: t);
   println("union contains point " +  u.process(v));     
}


/* Notes 
See the detailed discussion in
"Synthesizing Object-Oriented and Functional Design to Promote Re-use"
Section 3.4 figures 12
http://citeseer.nj.nec.com/krishnamurthi98synthesizing.html


square contains point false
circle contains point false
translated contains point true
shrunk translated contains point false
union contains point true
*/
-- IsaacGouy - 06 Feb 2004

Topic ExtensibleVisitorPatternExample . { Edit | Attach | Ref-By | Printable | Diffs | r1.6 | > | r1.5 | > | r1.4 | More }
Revision r1.6 - 25 Apr 2005 - 12:26 GMT - TWikiGuest
Parents: WebHome > CodeExamples > VisitorPatternMultiMethodExample
Copyright © 1999-2003 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback.