object Example {
trait Tree[+T] {
def elem: T
def left: Tree[T]
def right: Tree[T]
}
object EmptyTree extends Tree[Nothing] {
def elem = throw new NoSuchElementException("EmptyTree.elem")
def left = throw new NoSuchElementException("EmptyTree.left")
def right = throw new NoSuchElementException("EmptyTree.right")
}
class Branch[+T](val elem: T, val left: Tree[T], val right: Tree[T]) extends Tree[T] {
override def equals(other: Any) = other match {
case that: Branch[T] =>
this.elem == that.elem &&
this.left == that.left &&
this.right == that.right
case _ => false
}
}
}
object Test {
import collection.mutable.HashSet
import Example._
val b1 = new Branch[List[String]](Nil, EmptyTree, EmptyTree)
val b2 = new Branch[List[Int]](Nil, EmptyTree, EmptyTree)
b1 == b2 // true
}
So the pattern matching in case that: Branch[T] … is done at run time, which leads to the question: when are types checked at compile time and how do you tell?
Another related question: what types are erased? If all types are erased, then how do you know a certain object is of type Branch[_]?
0 comments:
Post a Comment