kotlin - 在构造函数中调用类的方法作为默认参数

标签 kotlin

我正在构造一个类,然后尝试调用该类的成员方法作为构造函数参数之一的默认值。

为什么这不是有效的 Kotlin?

// unresolved reference: defaultText
class MyThing(val text: String = defaultText()) {  
    fun defaultText() = "hi"
}

可以在 Java 和 Kotlin 中使用两个单独的构造函数,但这样我就失去了默认参数的简洁性。

class MyThing {

    private val text: String

    constructor(text: String) {
        this.text = text
    }

    constructor() {
        this.text = defaultText()
    }

    private fun defaultText(): String {
        return "hi"
    }
}

最佳答案

让构造函数的默认参数表达式调用同一实例的成员函数的最大问题是在调用构造函数之前对默认参数进行求值。

鉴于此,这样的成员函数必须在完全未初始化的类实例上运行(因为即使是 super 构造函数也会在此之后工作,see this answer 关于执行顺序)。

通常,成员函数执行一些逻辑时会考虑实例状态,并且在空实例上运行成员函数可能会破坏某些逻辑(例如,所有字段都将保留 null,甚至Kotlin 非空属性的支持字段)。总的来说,即使此类调用在运行时没有失败,它们也可能会引入微妙的错误,因此禁止使用完全未初始化的实例。

关于辅助构造函数,嗯,至少它在 super 构造函数初始化实例的某些部分之后运行,因此该部分并不是完全空的,但您需要确保不使用未初始化的类(如果这样做,您可能会再次遇到运行时故障或引入错误)。

我宁愿建议使用 companion object 的函数(这些在首次使用类之前初始化)为此目的:

class MyThing(val text: String = defaultText()) {  
    companion object {
        fun defaultText() = "hi"
    }
}

甚至是顶级函数:

fun defaultText() = "hi"

class MyThing(val text: String = defaultText())

关于kotlin - 在构造函数中调用类的方法作为默认参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46575059/

相关文章:

spring-boot - Spring-Boot 是否处理 WebFlux 上下文之外的 Kotlin 协程?

unit-testing - 如何对 Kotlin 挂起函数进行单元测试

kotlin - 如何在 Kotlin 中扩展枚举?

kotlin - Corda: error=org.hibernate.InstantiationException: 没有实体的默认构造函数

spring-boot - lateinit 属性 S 尚未初始化

android - Dagger /MissingBinding java.util.Map<java.lang.Class<? extends ViewModel>,Provider<ViewModel>> 不能在没有 @Provides 注释的方法的情况下提供

java - 当除法结果包含除法余数时如何增加除法结果?

java - 如何将整数数组传递给需要 `Array<T>` 的方法?

android - SetupWithNavController 不适用于工具栏

android - 如何等到监听器完成执行