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
eval
method 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.