как идиоматично написать этот код в Котлине?
fun createAnswerValue(record: Record): QuestionnaireResponseItemComponent{
val list = createAnswerList(record)
if (list.isNotEmpty()) {
return QuestionnaireResponseItemComponent().apply {
linkId = record.siblingIndexUID
answer = list
}
}
return null
}
Это может быть однострочный.
ОБНОВЛЕНИЕ: как упоминалось в комментариях @Tenfour04, было бы более эффективно сначала проверить список на предмет отсутствия обнуления:
fun createAnswerValue(): QuestionnaireResponseItemComponent? =
createAnswerList(record)
?.takeIf { it.isNotEmpty() }
?.let {
QuestionnaireResponseItemComponent(
linkId = record.siblingIndexUID,
answer = it
)
}
@ Tenfour04 Tenfour04 он по-прежнему всегда создает этот объект Component до того, как будет рассмотрен предикат takeIf
, верно? (Возможность вызова isNotEmpty
в списке означает, что createAnswerList
не может возвращать значение null)
@cactustictacs, поэтому я сказал, что его нужно убрать из разрешения.
@ Tenfour04 Tenfour04 да, это то, что я имею в виду - let все равно будет работать и возвращать значение до того, как следующий takeIf запустит это значение, верно? Я просто удостоверяюсь, что ничего не упускаю, так как я сделал версию, которая этого избегает!
@cactustictacs, вот что я предлагаю: createAnswerList(record)?.takeIf { it.isNotEmpty() } ?.let { QuestionnaireResponseItemComponent(linkId = record.siblingIndexUID, answer = it) }
, но с каждой функцией в отдельной строке для удобства чтения.
@ Tenfour04 Спасибо! Обновлен ответ
@ Tenfour04 аааа, ок, понял, я думал, ты имеешь в виду пометить это в конце let
, просто из-за того, где оно уже было. Спасибо!
Лично я бы сделал так:
fun createAnswerValue(record: Record): QuestionnaireResponseItemComponent? {
val list = createAnswerList(record)
return if (list.isNotEmpty()) QuestionnaireResponseItemComponent().apply {
linkId = record.siblingIndexUID
answer = list
} else null
}
что в значительной степени то, что у вас уже было, просто с использованием else
и в результате с поднятым return
. Это просто и читабельно!
Если вы хотите использовать takeIf
, как в ответе @Mihail, я бы, вероятно, сделал это следующим образом:
fun createAnswerValue(): QuestionnaireResponseItemComponent? =
createAnswerList(record)
.takeIf { it.isNotEmpty }
?.let { list ->
QuestionnaireResponseItemComponent().apply {
linkId = record.siblingIndexUID
answer = list
}
}
разница в том, что в этом объект создается только в том случае, если он будет возвращен - если вам все равно, то версия Михаила явно более компактна!
Но эта версия Kotliny делает то же самое, что и if/else
, которую я опубликовал — я бы сказал, что эта версия более читабельна, чем эта (хотя это не так уж плохо). Объединение нескольких вызовов вместе может сделать вещи красивыми, читабельными и элегантными, но также может чрезмерно усложнить вещи и затруднить точное понимание того, что происходит. И я определенно написал свою справедливую долю этого! Поэтому я чувствую, что с «идиоматическим» кодом нужно быть осторожным — знать свои варианты — это хорошо! Но используйте то, что работает, не думайте, что вам нужно использовать языковую функцию, потому что она есть, IMO
Я бы убрал
takeIf
изlet
для удобочитаемости и во избежание создания ненужных объектов.