Nice TWiki > Doc > CodeExamples > VisitorPatternMultiMethodExample (r1.1) TWiki webs:
Dev | Doc | Main | TWiki | Sandbox
Doc . { Changes | Index | Search | Go }
Other approaches: FunctionalReuseExample?, CompositePatternExample, VisitorPatternExample, ExtensibleVisitorPatternExample.

/* Please try the NoviceExamples before the MultiMethodExamples
To compile:
   nicec --sourcepath .. -a multimethod.jar multimethod
To run:
   java -jar multimethod.jar
*/


// Multimethods: Types and Tools
//------------------------------

abstract class Shape {
   boolean containsPoint(Point p);
}

class Square extends Shape { 
   double side; 

   containsPoint(p) {
      let d = side/2;
      return 
         (p.x >= -d && p.x < d) && 
         (p.y >= -d && p.y < d);
   }
}

class Circle extends Shape { 
   double radius; 

   // just test the bounding box
   containsPoint(p) {      
      return 
         (p.x >= -radius && p.x < radius) && 
         (p.y >= -radius && p.y < radius);
   }
}

class Translated extends Shape { 
   Point d; 
   Shape shape; 

   containsPoint(p){
      let p' = 
         new Point(
            x: p.x - d.x,
            y: p.y - d.y );
 
      return shape.containsPoint(p');
   }
}

class Point { double x; double y; }



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


// Multimethods: Adding Type Variants
//-----------------------------------

class Union extends Shape {
   Shape shape1; 
   Shape shape2; 

   containsPoint(Point p) =
      shape1.containsPoint(p) || shape2.containsPoint(p);
}



// Multimethods: Adding Tools
//---------------------------

Shape shrink(Shape s, double toPercent);

shrink(Square s, toPercent) = 
   new Square(side: (s.side*toPercent)/100);
   
shrink(Circle s, toPercent) = 
   new Circle(radius: (s.radius*toPercent)/100);

shrink(Translated s, toPercent) = 
   new Translated(d: s.d, shape: s.shape.shrink(toPercent)); 
   
shrink(Union s, toPercent) =
   new Union(
      shape1: s.shape1.shrink(toPercent),
      shape2: s.shape2.shrink(toPercent)   
   );  



// Multimethods: 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);

   println("square contains point " + s.containsPoint(p));
   println("circle contains point " + c.containsPoint(p));
   println("translated contains point " + t.containsPoint(p));


   let t' = t.shrink(toPercent: 50);
   println(
      "shrunk translated contains point " + 
         t'.containsPoint(p));
                            
   let u = new Union(shape1: s, shape2: t);
   println("union contains point " +  u.containsPoint(p));            
}



/* Notes 
See the detailed discussion in
"Synthesizing Object-Oriented and Functional Design to Promote Re-use"
Section 7 p110
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 VisitorPatternMultiMethodExample . { Edit | Attach | Ref-By | Printable | Diffs | r1.7 | > | r1.6 | > | r1.5 | More }
Revision r1.1 - 06 Feb 2004 - 04:41 GMT - IsaacGouy
Parents: WebHome > CodeExamples
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.