Действительно ли это - надлежащий способ инициализировать нулевые ссылки в Scala?

Скажем, у меня есть a MyObject экземпляр, который не инициализируется:

var a:MyObject = null

действительно ли это - надлежащий способ инициализировать его к пустому указателю?

51
задан Geo 13 March 2010 в 11:38
поделиться

3 ответа

Альтернативы

В крайнем случае используйте null . Как уже упоминалось, Опция заменяет большинство случаев использования null. Если вы используете null для реализации отложенной инициализации поля с некоторыми дорогостоящими вычислениями, вам следует использовать lazy val .

Каноническая инициализация нулевым значением

Тем не менее, Scala поддерживает null . Я лично использую его в сочетании с Spring Dependency Injection.

Ваш код полностью действителен. Однако я предлагаю вам использовать var t: T = _ для инициализации t значением по умолчанию. Если T является примитивом, вы получите значение по умолчанию, зависящее от типа. В противном случае вы получите null .

Это не только более сжато, но и необходимо, когда вы заранее не знаете, каким будет T :

scala> class A[T] { var t: T = _ }
defined class A

scala> new A[String].t
res0: String = null

scala> new A[Object].t            
res1: java.lang.Object = null

scala> new A[Int].t   
res2: Int = 0

scala> new A[Byte].t
res3: Byte = 0

scala> new A[Boolean].t
res4: Boolean = false

scala> new A[Any].t   
res5: Any = null

Расширенный

Использование var t: T = null является ошибкой компиляции, если T не ограничен:

scala> class A[T] { var t: T = null }
<console>:5: error: type mismatch;
 found   : Null(null)
 required: T
       class A[T] { var t: T = null }

Вы можете добавить неявный параметр в качестве доказательства того, что T допускает значение NULL - подтип AnyRef , а не подтип NotNull Это не полностью запеченное , даже в Scala 2.8, так что пока просто считайте это любопытством.

scala> class A[T](implicit ev: Null <:< T) { var t: T = null }           
defined class A
62
ответ дан 7 November 2019 в 10:05
поделиться

Канонический ответ: не используйте null. Вместо этого используйте тип опции:

var a = None : Option[MyObject]

Когда вы хотите установить его:

a = Some(foo)

И когда вы хотите прочитать из него, проверьте на None:

a match {
  case None => Console.println("not here")
  case Some(value) => Console.println("got: "+value)
}
32
ответ дан 7 November 2019 в 10:05
поделиться

Как уже отметили Дэвид и retronym, в большинстве случаев целесообразно использовать Option, поскольку Option делает более очевидным, что вы должны обработать ситуацию без результата. Однако возврат Some(x) требует создания объекта, а вызов .get или .getOrElse может быть дороже, чем if-выражение. Таким образом, в высокопроизводительном коде использование Option не всегда является лучшей стратегией (особенно в коде просмотра коллекции, где вы можете искать значение очень много раз и не хотите, чтобы было создано соответствующее количество объектов). С другой стороны, если вы делаете что-то вроде возврата текста всей веб-страницы (которой может не существовать), нет причин не использовать Option.

Также, чтобы добавить к замечанию retronym о дженериках с null, вы можете сделать это в полной мере, если вы действительно хотите, чтобы это было null:

class A[T >: Null] { var t: T = null }

и это работает в 2.7 и 2.8. Это немного менее общий метод, чем <:<, потому что он не подчиняется NotNull AFAIK, но в остальном он делает именно то, на что вы надеетесь.

8
ответ дан 7 November 2019 в 10:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: