Как работают общие ограничения scala для обнуляемых типов - PullRequest
13 голосов
/ 25 февраля 2010

Я пытался двумя способами ограничить типовой параметр типа обнуляемым типом, но оба, похоже, имеют некоторые неожиданные проблемы.

Первая попытка (с использованием T <: AnyRef): </p>

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))

Это, кажется, делает именно то, что я хочу, но я не понимаю, почему ноль должен быть приведен к T.


Вторая попытка (с использованием 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

Это не требует приведения на null, но позволяет передавать AnyVals и преобразовывать тип в любой, что я не искал.

Кто-нибудь знает, почему эти два разных подхода работают так же, как и они?

1 Ответ

22 голосов
/ 25 февраля 2010
def testAnyRefConstraint[T >: Null <: AnyRef](option:Option[T]):T = {
  option getOrElse null
}

Я чувствовал себя действительно глупо, когда совершил эту ошибку в первый раз. То, что что-то распространяется AnyRef, не означает, что оно должно быть обнуляемым. Например, Nothing - это подтип AnyRef, и он не может быть пустым.

Обратный подход аналогичен, потому что Any является супертипом Null, а любой Int также является Any.

...