是否有一种惯用的方法来让(辅助)构造函数为Kotlin中的主要构造函数派生值?

Tra*_*ggs 1 kotlin

我有一个简单的Kotlin类:

data class ValveSpan(val begin:Duration, val end:Duration, val key:String):Comparable<ValveSpan> {
    ...
}
Run Code Online (Sandbox Code Playgroud)

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

但是当我想创建一个辅助构造函数来填充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????
}
Run Code Online (Sandbox Code Playgroud)

基本上,次级构造的意图,是取输入,计算一些值作为主要的构造,然后调用与这些值的初级.但似乎我必须在主构造函数中内联它们.随着派生变得越来越复杂,越来越复杂.我真的很想写下这样的东西:

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)
}
Run Code Online (Sandbox Code Playgroud)

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

wha*_*ley 6

要添加@ 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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

那将允许你打电话ValveSpan(doc).

  • 不知道,好:) (2认同)