Search code examples
scalagenericsscala-2.11

Casting null to an instance of a case class in Scala


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"


Solution

  • Because Type Patterns are defined so:

    • A reference to a class C, p.C, or T#C. This type pattern matches any non-null instance of the given class.

    So: null is a perfectly valid value of type W; but it won't be matched by the pattern w: W.

    And the main reason why it isn't matched is precisely

    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.

    so when you match against w: W you want to know its fields and methods are available. But for null they aren't.