当传递null时,有没有办法在非可选参数上使用默认值?

Bry*_*yan 32 nullable default-parameters kotlin

例如,如果我有以下数据类:

data class Data(
    val name: String = "",
    val number: Long = 0
)
Run Code Online (Sandbox Code Playgroud)

和可以返回的功能null:

fun newName(): String? {}

fun newNumber(): Long? {}
Run Code Online (Sandbox Code Playgroud)

我知道如果不是,我可以使用以下代码来使用函数的值null:

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

val data = Data(
        if (newName != null) newName else "",
        if (newNumber != null) newNumber else 0
)
Run Code Online (Sandbox Code Playgroud)

但有没有办法在值为时使用Data类的构造函数中指定的默认值null?

我在文档中找不到任何内容,但我希望这样的东西能够工作:

val data = Data(newName()?, newNumber()?)
Run Code Online (Sandbox Code Playgroud)

但那不编译.

mfu*_*n26 27

您可以在接收时创建使用相同默认值的辅助构造函数null:

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

  • 哦,这是一个很好的解决方法!虽然,它让我希望这样的东西被内置到语言中; 如果只是为了摆脱样板. (6认同)

hol*_*ava 13

辅助构造函数仅支持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)
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用invoke运算符,例如:

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

如果类不是数据类,那么您可以从参数延迟初始化属性,而不是在主构造函数上定义属性,例如:

class Data(name: String? = null, number: Long? = null) {
    val name = name ?: ""
    val number = number ?: 0
}
Run Code Online (Sandbox Code Playgroud)