I have a piece of code that relies on the existence of an arbitrary element of a certain case class in order to operate on the class's fields. There are some options out there, and even though pretty much every Scala blog recommends not using null ever, it seems like not a terrible idea in type level programming (e.g. this answer: https://stackoverflow.com/a/4443972/1650448). However, this code directly casting null to a particular case class does not work and does not throw an error, and I'm interested in why.
trait V {}
case class W(x: Int) extends V
val y = null.asInstanceOf[W]
y match {
case w:W => println("null cast to W is a W")
case _ => println("null cast to W is NOT a W")
}
// prints "null cast to W is NOT a W"
y match {
case v:V => println("null cast to W is a V")
case _ => println("null cast to W is NOT a V")
}
// prints "null cast to W is NOT a V"
val z = W(1)
z match {
case w:W => println("instantiated W is a W")
case _ => println("instantiated W is NOT a W")
}
// prints "instantiated W is a W"
z match {
case v:V => println("instantiated W is a V")
case _ => println("instantiated W is NOT a V")
}
// prints "instantiated W is a V"
Because Type Patterns are defined so:
So:
nullis a perfectly valid value of typeW; but it won't be matched by the patternw: W.And the main reason why it isn't matched is precisely
so when you match against
w: Wyou want to know its fields and methods are available. But fornullthey aren't.