Скала присваивает вальс
Почему не возможно иметь это:
def main(args:Array[String]) {
val whatever:String // Have it uninitialized here
if(someCondition) {
whatever = "final value" // Initialize it here
}
}
Я не понимаю, почему это не должно быть законным. Я знаю, что могу сделать это var
, но почему мы должны инициализировать val
когда мы это объявим? Разве не кажется более логичным иметь возможность инициализировать его позже?
5 ответов
Ты можешь сделать:
val whatever =
if (someCondition)
"final value"
else
"other value"
Решение Java на самом деле является обходным решением проблемы, когда не все выражения возвращают значения, поэтому вы не можете написать это на Java:
final String whatever = if (someCondition) {
"final value"
} else {
"other value"
}
Все чаще в Java все чаще используют троичный оператор:
final String whatever = someCondition ? "final value" : "other value"
Что хорошо для этого ограниченного варианта использования, но совершенно несостоятельно, когда вы начинаете работать с операторами switch и несколькими конструкторами.
Подход Скалы здесь другой. Вся конструкция объекта должна в конечном итоге проходить через один "первичный" конструктор, все выражения возвращают значение (даже если оно Unit
, эквивалентный Java Void
), и внедрение в конструктор сильно приветствуется. Это приводит к тому, что графы объектов создаются в виде ориентированного ациклического графа, а также очень хорошо работают с неизменяемыми объектами.
Вы также хотите знать, что объявление и определение переменных в отдельных операциях, как правило, является плохой практикой при работе с несколькими потоками и может сделать вас уязвимым для выставления нулей и условий гонки, когда вы меньше всего их ожидаете (хотя это не так). действительно проблема при строительстве объекта). Атомарное создание неизменных значений - это только один аспект того, как функциональные языки помогают справиться с параллелизмом.
Это также означает, что компилятор Scala может избежать некоторых ужасно сложных потоков анализа из спецификации языка Java.
Как уже говорилось, Scala Way ™ - это:
val whatever =
if (someCondition)
"final value"
else
"other value"
Подход, который также масштабируется до других структур управления:
val whatever = someCondition match {
case 1 => "one"
case 2 => "two"
case 3 => "three"
case _ => "other"
}
Приложив немного опыта Scala, вы обнаружите, что этот стиль помогает компилятору помочь вам, и вы должны сами писать программы с меньшим количеством ошибок!
Использование lazy val
вот так:
def main(args:Array[String]) {
lazy val whatever:String = if (someCondition) "final value" else "other value"
// ...
println(whatever) // will only initialize on first access
}
В дополнение к тому, что сказали другие, обратите внимание, что Java допускает "чистые конечные" "переменные", что мне очень не нравится:
final Boolean isItChristmasYet;
if (new Date().before(christmas)) {
isItChristmasYet = Boolean.FALSE;
} else {
isItChristmasYet = Boolean.TRUE;
}
Однако, благодаря анализу потока данных в компиляторе, javac не позволит вам оставить свой whatever
переменная не назначена, если someCondition
не держит
Потому что цель 'val' - сообщить читателю (и компилятору): "Это значение останется тем, к чему оно инициализировано, до тех пор, пока оно не прекратит свое существование"
Это не имеет большого смысла без инициализации.
Конечно, можно придумать что-то вроде val(3), который допускает три присваивания переменной, но я не думаю, что это будет полезно.