在构造函数中将类的方法作为默认arg调用

时间:2017-10-04 22:20:46

标签: kotlin

我构建一个类,然后尝试将该类的成员方法作为其中一个构造函数args的默认值。

为什么这个有效的Kotlin?

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

在Java和Kotlin中使用两个独立的构造函数是可能的,但是我失去了默认args的简洁性。

class MyThing {

    private val text: String

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

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

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

1 个答案:

答案 0 :(得分:2)

使构造函数的默认参数表达式调用同一实例的成员函数的最大问题是在调用构造函数之前计算默认参数

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

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

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

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

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

甚至是顶级功能:

fun defaultText() = "hi"

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