#scala
Вопрос:
Я просматриваю книгу Scala.
Вот пример:
def toInt(s: String): Option[Int] = {
try {
Some(Integer.parseInt(s.trim))
} catch {
case e: Exception => None
}
}
val x = null
println(toInt(x)) // < ---- why compiler does not complain about Null ?
toInt
должно разрешаться только String
в качестве аргумента, но компилятор согласен с null.
Почему? Такое поведение запрещено в Rust и TypeScript.
Есть ли какой-нибудь флаг или что-то еще ?
Комментарии:
1. Да, Котлин тоже все правильно понял. Несмотря на все то, что Scala проделала замечательную работу, оставить
null
без внимания, возможно, самое худшее решение в Scala. Похоже, Дотти может что-то сказать по этому поводу , чего бы это ни стоило2. @SilvioMayolo Котлин, по крайней мере, попытался сделать это правильно, но довольно скоро обнаружил, что это легче сказать, чем сделать ; однако я не проверял, произошли ли какие-либо недавние изменения в этом направлении.
3. Может быть, также стоит объяснить, почему это отличается в TS и Rust. 1. У TS в качестве основы был JS, а у JS вообще не было системы типов. Таким образом, система типов TS была в основном проектом «зеленого поля», и у нее была возможность «сделать это правильно» с самого начала (что она и сделала, довольно успешно). Этого не было в случае с Java, в которой это уже было
String
включеноnull
и т. Д. 2. Аналогично для Rust: is не должен был быть совместим с любыми токсичными аннотациями устаревшего типа, поэтому он поступил правильно и полностью исключилnull
концепцию.4. Спасибо за объяснение @Андрей Тюкин
Ответ №1:
Option
может помочь, потому что Option(null) == None
def toInt(s: String): Option[Int] =
Option(s).flatMap(_.toIntOption)
toInt(null) // None
но обычно мы предвосхищаем это такими подписями, как
def toInt(s: Option[String]): Option[Int]
и оберните устаревшие API, которые могут возвращать значение null, слоем Scala
toInt(Option(legacyJavaApi()))
Также линтеры, такие как Wartremover, могли бы помочь: https://www.wartremover.org/doc/warts.html#null
Иногда бывает полезен трюк var x: A = null.asInstanceOf[A]
с инициализацией, где A
находится параметр типа, потому что в противном случае чему бы вы назначили x
?.
Комментарии:
1. Есть
null
ли какой-то супертип для всех типов?2. @капитан-йоссариан Это подтип любого другого ссылочного типа. Начиная с Scala 3, его можно изменить так, чтобы он был только подтипом
Any
с-Yexplicit-nulls
флагом.