scala/epReg2.scala
// register operation by Operation subtypes
// traits
trait Op {
def op : Op
def evalOp(d: BaseD): Int
}
trait BaseD {
def op: Op
}
// primary implementation IntD with eval
class IntD(val value: Int) extends BaseD {
def op() = IntD.op
}
class IntEval extends Op {
def evalOp(d: BaseD) = d.asInstanceOf[IntD].value
}
object IntD {
var op: Op = new IntEval()
}
object eval {
def apply(d: BaseD) = d.op.evalOp(d)
}
// data extension: PlusD
class PlusEval extends Op {
def evalOp(d: BaseD) = eval(d.asInstanceOf[PlusD].l) + eval(d.asInstanceOf[PlusD].r)
}
class PlusD(val l: BaseD, val r: BaseD) extends BaseD {
def op = PlusD.op
}
object PlusD {
var op = new PlusEval
}
// operation extension
trait ReprOp extends Op {
def reprOp(d: BaseD): String
}
class IntRepr extends IntEval with ReprOp {
def reprOp(d: BaseD) = d.asInstanceOf[IntD].value.toString
}
class PlusRepr extends PlusEval with ReprOp {
def reprOp(d: BaseD) = {val r = d.asInstanceOf[PlusD]; repr(r.l) + '+' + repr(r.r)}
}
object repr {
def apply(d: BaseD) : String =
{ d.op match
{
case r: ReprOp => r.reprOp(d)
case r =>
{
println("repr ini .....")
IntD.op = new IntRepr()
PlusD.op = new PlusRepr()
repr(d)
}
}
}
}
// show the elements
object EpReg1 { def show =
{
val i1 = new IntD(11)
val i2 = new IntD(22)
val p3 = new PlusD(i1, i2)
val p4 = new PlusD(p3, new PlusD(new IntD(4), new IntD(44)))
var nm : String = "??"
for (e <- List("i1", i1, "i2", i2, "p3", p3, "p4", p4)) {
e match {
case s: String => nm = s
case d: BaseD => { println(nm + " " + d + " eval " + eval(d))
println( " " + d + " eval " + eval(d) + " repr " + repr(d))
}
}
}
}
}