Visitor Pattern UseCase in Scala using Pattern Matching and Traits



Introduction
Make your Iterable stack object visitable using Trait. I am using the Stack Implementation of the previous post. Scala code presented here illustrates several features of Scala language. Generics ( Parameterized types), Pattern Matching and Traits. 


Program

package com.rajeshpatkar

object Program {
  def main(args: Array[String]): Unit = {
    val p1 = Point2D(1,2)
    val p2 = Point3D(5,6,7)
    val p3 = PointPolar(1,34)
    (Stack[Point]() < p1 < p2 < p3 ~).visit(_*2).visit(_*33).visit(_-2);
  }
}

abstract class Point
case class Point2D(val x:Int , val y:Int) extends Point
case class Point3D(val x:Int,val y:Int,val z:Int) extends Point
case class PointPolar(val r:Int ,val theta:Int) extends Point

trait Visitable[T]{
  def visit(p:(Int)=>Int):T
}

case class Stack[T] extends Iterable[T] with Visitable[Stack[T]]{
  class Node (val value : T , val next : Node);
  var h : Node = null;
  def < ( value : T ) :Stack[T]= { h = new Node(value,h); this }
  def > (op: (Option[T])=>Unit):Stack[T] = { 
         var value:Option[T] = if(h == null) None
                     else {
                            val t = h.value
                            h = h.next
                            Some(t)
                     }  
         op(value)           
         println("Value Popped -->" + value)     
         this 
  }
  def ~ () : Stack[T] = { 
                       println("Printing Stack...")
                       foreach(println)
                       this;
  }
  override def iterator():Iterator[T] = {
                              var data = List[T]()
                              var temp = h;
                              while(temp != null){
                                  data = temp.value::data
                                  temp=temp.next
                              }
                              data.iterator
  }
                                              
  override def visit(p:(Int)=>Int):Stack[T] = 
  {
     for(v <- iterator){
       v match {
         case Point2D(x,y) => 
              println("x = "+ p(x)+ " y = " + p(y))
         case Point3D(x,y,z) => 
              println("x = "+ p(x) +" y = "+ p(y) +" z = "+ p(z))
         case PointPolar(r,theta) => 
              println("r = " + p(r) + " theta = "+ p(theta))
         case _ => println("Match not found")
       }    
     }
     this
  }

 }


Output

Point2D(1,2)
Point3D(5,6,7)
PointPolar(1,34)
x = 2 y = 4
x = 10 y = 12 z = 14
r = 2 theta = 68
x = 33 y = 66
x = 165 y = 198 z = 231
r = 33 theta = 1122
x = -1 y = 0
x = 3 y = 4 z = 5

r = -1 theta = 32


copyright ©Rajesh Patkar, All rights reserved.

Comments

Popular posts from this blog

Harikavach ( Level 3 )

Potter Metaphor.

Grapes a Metaphor