Reputation: 51
Can some explain to me how I was able to create a case class with the wrong type? Bellow the worksheet output:
case class OptObj(os: Option[String], s: String)
//defined class OptObj
val osCrazy: Option[Any] = Option(Option(Option(1)))
//osCrazy: Option[Any] = Some(Some(Some(1)))
def anyOpt: Option[Any] = osCrazy
//anyOpt: Option[Any]
def getOpt[T]: Option[T] = anyOpt.map(_.asInstanceOf[T])
//getOpt: [T]=> Option[T]
val o = OptObj(getOpt[String], "It has the wrong type inside, but was built!")
//o: OptObj = OptObj(Some(Some(Some(1))),It has the wrong type inside, but was built)
o == OptObj(None,"")
//res0: Boolean = false
o == o
//res1: Boolean = true
o.os
//res2: Option[String] = Some(Some(Some(1)))
o.os.get
//java.lang.ClassCastException: scala.Some cannot be cast to java.lang.String
The object is created with the wrong type inside, shouldn't object creation fail? It just fails when I try to make some operation on the os attribute.
Upvotes: 2
Views: 99
Reputation: 990
The documentation for Any.asInstanceOf
explains what you are seeing. The short of it is that the code compiles due to type erasure.
Note that the success of a cast at runtime is modulo Scala's erasure semantics. Therefore the expression
1.asInstanceOf[String]
will throw aClassCastException
at runtime, while the expressionList(1).asInstanceOf[List[String]]
will not. In the latter example, because the type argument is erased as part of compilation it is not possible to check whether the contents of the list are of the requested type.
Upvotes: 3