有没有惯用的方法让(辅助)构造函数派生出Kotlin中主要构造函数的值?

时间:2018-09-24 17:34:46

标签: kotlin

我有一个简单的Kotlin课:

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

因为它是一个数据类,所以我必须有一个带有一个或多个值的主构造函数。很好,我喜欢它的简洁表达。

但是当我想创建一个第二个构造函数来从像对象这样的文档中填充一个(类似于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)
}

是否无需委托所有内联计算就可以委托给主构造函数?

2 个答案:

答案 0 :(得分:6)

要添加@ ahmed-ashraf-gamal的answer,您还可以通过在伴侣对象上定义定义调用操作符的伴侣对象,来模拟从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)

答案 1 :(得分:2)

您可以为此使用伴随对象:

data class ValveSpan(val begin:Duration, val end:Duration, val key:String) {
    companion object {
        fun fromDoc(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.fromDoc(doc)