Есть ли способ использовать значение по умолчанию для необязательного параметра, когда передается значение NULL?

Например, если у меня есть следующий класс данных:

data class Data(
    val name: String = "",
    val number: Long = 0
)

И функции, которые могут вернуть null:

fun newName(): String? {}

fun newNumber(): Long? {}

Я знаю, что могу использовать следующее, чтобы использовать значение функций, если они не null:

val newName = newName()
val newNumber = newNumber()

val data = Data(
        if (newName != null) newName else "",
        if (newNumber != null) newNumber else 0
)

Но есть ли способ просто использовать значение по умолчанию, указанное в конструкторе Data класс, когда значения null?

Я не мог найти ничего в документации, но я надеялся, что что-то вроде этого будет работать:

val data = Data(newName()?, newNumber()?)

Но это не компилируется.

3 ответа

Вы можете создать вторичный конструктор, который использует те же значения по умолчанию при получении null:

data class Data(
        val name: String = "",
        val number: Long = 0
) {
    constructor(
            name: String? = null,
            number: Long? = null
    ) : this(
            name ?: "",
            number ?: 0
    )
}

Вторичный конструктор поддерживает только примитивные свойства Nullable. это означает, что это приведет к 2 одинаковым конструкторам, если свойство не является примитивным типом, например:

data class Data(val name: String) {
    constructor(name: String? = null) : this(name ?: "foo");
    // ^--- report constructor signature error                
}

data class Data(val number: Long = 0) {
     constructor(number: Long? = null) : this(number ?: 0)
     //                  ^--- No problem since there are 2 constructors generated:
     //                       Data(long number) and Data(java.lang.Long number)
}

альтернативный способ использует invoke оператор для этого, например:

data class Data(val name: String) {
    companion object {
        operator fun invoke(name: String? = null) = Data(name ?: "")
    }
}

Если класс не является классом данных, то вы можете лениво инициализировать свойства из параметров, а не определять свойства в основном конструкторе, например:

class Data(name: String? = null, number: Long? = null) {
    val name = name ?: ""
    val number = number ?: 0
}

Если нужно, могу предложить другое решение:

      data class Data(
    val inputName: String?,
    val inputNumber: Long?
) {
    private val name = inputName ?: ""
    private val number = inputNumber ?: 0
}
Другие вопросы по тегам