2010-02-25 24 views
11

He intentado dos formas de restringir un tipo de parámetro genérico a un tipo anulable, pero ambos parecen tener algunos problemas inesperados.Cómo funcionan las restricciones genéricas scala a tipos anulables

primer intento (utilizando 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)) 

Esto parece hacer exactamente lo que yo quiero, pero no entiendo por qué la hipótesis nula debe ser echado a un T.


Segundo intento (con T>: nulo):

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 

Esto no requiere el elenco de nulo, pero permite pasar AnyVals y convierte el tipo en any, que no es lo que estaba buscando.

¿Alguien tiene alguna idea de por qué estos dos enfoques diferentes funcionan de la manera en que lo hacen?

Respuesta

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

Me sentí realmente estúpido cuando cometí este error la primera vez. El hecho de que algo se extienda AnyRef no significa que deba ser anulable. Por ejemplo, Nothing es un subtipo de AnyRef, y no puede contener nulos.

El revés es similar, ya que Any es un supertipo de Null, y cualquier Int es también un Any.

Cuestiones relacionadas