首页 > 解决方案 > 有没有一种惯用的方式来拥有一个(辅助)构造函数来为 Kotlin 中的主构造函数派生值?

问题描述

我有一个简单的 Kotlin 类:

data class ValveSpan(val begin:Duration, val end:Duration, val key:String):Comparable<ValveSpan> {
    ...
}

因为它是一个数据类,所以我必须有一个包含一个或多个值的主构造函数。没关系,我喜欢它简洁的表达方式。

但是,当我想创建一个辅助构造函数来填充来自 doc 之类对象(类似于 JSON)的构造函数时,它会变得很奇怪:

constructor(doc:TSON):this(doc["begin"].duration!!, doc["end"].duration!!, doc["valves"].sequence!!.first()!!.string!!) {
    // do nothing here, because, uh, I had to do it all in the delegated primary????
}

基本上,辅助构造函数的目的是获取输入,为主构造函数计算一些值,然后使用这些值调用主构造函数。但似乎我必须在主构造函数中内联它们。随着推导变得越来越复杂,它变得越来越复杂。我真的很想写一些类似的东西:

constructor(doc:TSON) {
    var sanitizedBegin =  doc["begin"].duration ?: 0.minutes
    var sanitizedEnd = doc["end"].duration ?: 0.minutes
    var sanitizedKey = doc["valves"].sequence?.firstOrNull()?.string ?: ""
    primaryConstructor(sanitizedBegin, sanitizedEnd, sanitizedKey)
}

有没有办法委托给主构造函数,而不必内联进行所有的桥接计算?

标签: kotlin

解决方案


要添加@ahmed-ashraf-gamal 的答案,您还可以通过引入一个在伴随对象上定义调用运算符的伴随对象来模拟从 ValveSpan 的客户端调用构造函数。例如:

data class ValveSpan(val begin:Duration, val end:Duration, val key:String) {
    companion object {
        operator fun invoke(doc:TSON): ValveSpan {
            var sanitizedBegin =  doc["begin"].duration ?: 0.minutes
            var sanitizedEnd = doc["end"].duration ?: 0.minutes
            var sanitizedKey = doc["valves"].sequence?.firstOrNull()?.string ?: ""
            return ValveSpan(sanitizedBegin, sanitizedEnd, sanitizedKey)
        }
    }
}

这将允许您调用ValveSpan(doc).


推荐阅读