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


// 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; }



// Visitor Pattern: Tools
//-----------------------

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; 
   
   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( 
         new ContainsPointVisitor(point: p'));
   }
}



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


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

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


class Union extends Shape {
   Shape shape1; 
   Shape shape2; 

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


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

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


// Visitor Pattern: Adding Tools
//------------------------------

<T| Shape <: T <: Shape>
class ShrinkVisitor<T> implements IShapeVisitor<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));        
}


// 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 ContainsPointVisitor(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) );  // FAILS AT RUNTIME
}


/* 

/* Notes 
See the detailed discussion in
"Synthesizing Object-Oriented and Functional Design to Promote Re-use"
Section 3.1 figures 7, 8, 9, 10, 11
http://citeseer.nj.nec.com/krishnamurthi98synthesizing.html


square contains point false
circle contains point false
translated contains point true
shrunk translated contains point false
Exception in thread "main" nice.tools.code.EnsureTypeProc has wrong type
*/
-- IsaacGouy - 06 Feb 2004

Topic VisitorPatternExample . { Edit | Attach | Ref-By | Printable | Diffs | r1.6 | > | r1.5 | > | r1.4 | More }
Revision r1.2 - 06 Feb 2004 - 15:18 GMT - IsaacGouy
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.