#kotlin
Вопрос:
Я хочу инициализировать два val в зависимости от того, является ли третья переменная нулевой или нет. Это работает:
class ABC(input: String?) {
private val x: Int
private val y: Int
init {
if (input != null) {
x = 1
y = 1
} else {
x = 2
y = 2
}
}
}
Но это не компилируется:
class ABC(input: String?) {
private val x: Int
private val y: Int
init {
input?.also {
x = 1
y = 1
} ?: also {
x = 2
y = 2
}
}
}
Почему второй пример приводит к ошибке? Разве логически это не то же самое, что и первое? Каков наиболее краткий способ достижения результата?
Ответ №1:
Он логически оценивает то же самое для людей, но слишком сложен для компилятора. Компилятор может обрабатывать одно if/else, но цепочка нулей и оператор Элвиса подобны двум отдельным операторам if. Ваш второй блок кода в основном похож на следующий, на который компилятор также будет жаловаться:
if (input != null) {
x = 1
y = 1
}
if (input == null) {
x = 2
y = 2
}
Цепочка функций области, подобных этой, в любом случае подвержена ошибкам, и ее следует избегать, когда это возможно. Ваш первый блок кода намного превосходит второй по удобочитаемости. Когда вы работаете со свойствами, допускающими обнуление, или вызываете ряд функций в стиле конструктора, тогда функции с цепочкой областей могут быть хорошим выбором. Но в данном случае input
это не свойство, поэтому вы можете написать более декларативный (т. Е. Более читаемый) код без цепочки функций области действия.
Я думаю, что это самый краткий способ инициализации ваших двух переменных, как вы их определили:
class ABC(input: String?) {
private val x: Int = if (input != null) 1 else 2
private val y: Int = x
}