scala/epDa1.scala
// Base data
trait BaseD {
def eval: Int
}
class IntD(val value: Int) extends BaseD {
def eval() = value
}
// data extension: PlusD
class PlusD(val l: BaseD, val r: BaseD) extends BaseD {
def eval() = l.eval + r.eval
}
// operation extension
trait ReprD extends BaseD {
def repr: String
}
class IntR(value: Int) extends IntD(value) with ReprD {
def repr() = value.toString
}
class PlusR(l: BaseD, r: BaseD) extends PlusD(l, r) with ReprD {
def repr() = "(" + l.asInstanceOf[ReprD].repr + '+' + r.asInstanceOf[ReprD].repr + ')'
}
object ReprD {
implicit def I2R(i: BaseD) = i.asInstanceOf[ReprD]
implicit def I2R(i: PlusD) = i.asInstanceOf[PlusR]
}
class PlusRA(l: BaseD, r: BaseD) extends PlusD(l, r) with ReprD {
def repr() = "(" + ReprD.I2R(l).repr + '+' + ReprD.I2R(r).repr + ')'
}
/*
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)))
val i5 = new IntR(55)
val i6 = new IntR(66)
val p7 = new PlusR(i5, i6)
val p8 = new PlusR(i5, i2)
val a9 = new PlusRA(i5, i6)
val aa = new PlusRA(i5, i2)
*/
/*
// data extension: PlusD
class PlusD(val l: BaseD, val r: BaseD) extends BaseD {
def eval() = l.eval + r.eval
}
def allT = (this, eval, repr)
def allS = this.toString + " =eval=> " + eval + " =repr=> " + repr
val a = new NumD(12)
(a, a eval, a repr)
a.allT
a.allS
new NumPlus(a, new NumD(98)) allS
new NumPlus(new NumPlus(new NumD(12), new NumD(34)), new NumD(98)) allS
// Base operation.
trait BaseOp {def computeNumD(data: NumD)}
// 1st concrete operation: evaluate the data
class EvalOp extends BaseOp {
var result: Option[Int] = _
def apply(data: BaseD) = {data.perform(this); result.get }
def computeNumD(data: NumD) {this.result = Some(data.value) }
}
// utility object for on-the-fly evaluations
object eval {def apply(data: BaseD) = new EvalOp()(data)}
*/