2014-12-10 6 views
3

Хорошо, я знаю, что лучше использовать нули в качестве дизайна, но в этом случае я должен. Почему следующее не компилируется?null как экземпляр параметра типа

def test[T<:AnyRef](o :Option[T]) :T = o getOrElse null 

Error:(19, 53) type mismatch; 
       found : Null(null) 
       required: T 
       Note: implicit method foreignKeyType is not applicable here because it comes after the application point and it lacks an explicit result type 
def test[T<:AnyRef](o :Option[T]) :T = o getOrElse null 
               ^
+0

почему бы вам не использовать 'Option.orNull'? –

+0

Это был мой первый выбор, но когда он не работал (по причине, приведенной в ответе ниже), я попытался упростить пример. – Turin

ответ

8

Null - это подтип всех ссылочных типов, но факт, что T является подтипом AnyRef, не гарантирует, что T является ссылочным типом - в частности, Nothing является подтипом AnyRef, который не содержит null.

Ваш код работает, если вы добавите нижнюю границу:

def test[T >:Null <:AnyRef](o :Option[T]) :T = o getOrElse null; 

Он работает:

scala> def test[T >:Null <:AnyRef](o :Option[T]) :T = o getOrElse null; 
test: [T >: Null <: AnyRef](o: Option[T])T 

scala> 

scala> 

scala> test(None) 
res0: Null = null 

scala> test(Some(Some)) 
res1: Some.type = Some 
+0

Нижняя граница необходима, потому что 'Nothing <: Null'. В противном случае вы можете создать экземпляр 'Nothing', используя' test [Nothing] (None) '. –

+0

Вы правы. Я исправлю. – jsalvata

+0

А теперь все ясно. Благодаря! – Turin

2

Я не знаю, почему это не работает - Null является подтипом всех ссылочных типов в Scala, поэтому можно было бы ожидать, что это будет работать с любым T <: AnyRef. Вы можете заставить его работать с asInstanceOf:

def test[T <: AnyRef](o: Option[T]): T = o getOrElse null.asInstanceOf[T] 

(Старайтесь избегать использования null всякий раз, когда это возможно в Scala - я могу представить вам бы законное использование случай, например, когда нужно передать данные в Java коде) ,

Кстати, Option есть метод orNull который будет возвращать значение опциона, если это Some и null если это None.

+1

Это будет NPE, если вызывается с параметром None. – jsalvata

+0

В REPL, но это может быть побочным эффектом REPL. Попробуйте это в REPL: 'test (None: Option [String])' – Jesper

+0

Вы правы. Тем не менее, решение использования>: Null вместо <: AnyRef (что эквивалентно, потому что все ссылочные типы попадают между этими двумя), более чистое, чем использование .asInstanceOf. – jsalvata

Смежные вопросы