As I was modelling expressions like Var("x") or Number(7) and writing an eval function with pattern matching, I ran into a case where I could not avoid using the ´asInstanceOf` method.
2 restrictions
I do not want to avoid pattern matching by declaring an
evalmethod in Expr and define it in its subclasses (cf. Expression problem, I prefer pattern match).I also do not want something like
Var("x", 7).
sealed trait Expr
object Expr {
def eval(e: Expr): Int = e match {
case Number(n) => n
case Var(_) => e.asInstanceOf[Var].getValue()
}
}
case class Number(n: Int) extends Expr
case class Var(s: String) extends Expr {
var value = 0
def getValue(): Int = value
def updateValue(x: Int): Unit = {
this.value = x
}
}
val x = Var("x")
x.updateValue(1)
Expr.eval(x) // 1
When I define the second case like this: case Var(x) => Var(x).getValue(), i get Expr.eval(x) // 0. This is, because Var(x) on the right side will construct a fresh Var with value 0.
I'm ok with using asInstanceOf but in the sense of improvement, I wonder if there is a cleaner solution than using asInstanceOf, which I haven't found yet.