How scala generic constraints to nullable types work

六月ゝ 毕业季﹏ 提交于 2019-12-05 12:51:03

问题


I've tried two ways to constrain a generic type parameter to a nullable type, but both seem to have some unexpected problems.

First attempt (using T <: AnyRef):

scala> def testAnyRefConstraint[T <: AnyRef](option:Option[T]):T = {
     | //without the cast, fails with compiler error:
     | //    "found: Null(null) required: T"
     | option getOrElse null.asInstanceOf[T]
     | }
testAnyRefConstraint: [T <: AnyRef](Option[T])T

scala> testAnyRefConstraint(Some(""))
res0: java.lang.String = 

scala> testAnyRefConstraint(Some(0))
<console>:16: error: inferred type arguments [Int] do not conform to method testAnyRefConstraint's type parameter bounds [T <: AnyRef]
       testAnyRefConstraint(Some(0))

This seems to do exactly what I want, but I don't understand why the null needs to be cast to a T.


Second attempt (using T >: Null):

scala> def testNullConstraint[T >: Null](option:Option[T]):T = {
     | option getOrElse null
     | }
testNullConstraint: [T >: Null](Option[T])T

scala> testNullConstraint(Some(""))
res2: java.lang.String = 

scala> testNullConstraint(Some(0))
res3: Any = 0

This doesn't require the cast on null, but it allows AnyVals to be passed and converts the type to any, which is not what I was looking for.

Does anyone have any idea why these two different approaches work the way that they do?


回答1:


def testAnyRefConstraint[T >: Null <: AnyRef](option:Option[T]):T = {
  option getOrElse null
}

I felt really stupid when I made this error the first time. Just because something extends AnyRef doesn't mean it must be nullable. For instance, Nothing is a subtype of AnyRef, and it is not nullable.

The other way around is similar, because Any is a supertype of Null, and any Int is also an Any.



来源:https://stackoverflow.com/questions/2336204/how-scala-generic-constraints-to-nullable-types-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!