Нет ли идиоматического способа иметь (вторичный) конструктор, который получает значения для первичного конструктора в Kotlin? - PullRequest
0 голосов
/ 24 сентября 2018

У меня есть простой класс 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)
}

Нет ли способа делегировать первичному конструктору без необходимости выполнять все встроенные вычисления моста?

Ответы [ 2 ]

0 голосов
/ 24 сентября 2018

Чтобы добавить к ответу @ ahmed-ashraf-gamal, вы также можете смоделировать вызов конструктора из клиентов ValveSpan, введя объект-компаньон, который определяет оператор invoke для объекта-компаньона.Например:

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).

0 голосов
/ 24 сентября 2018

Для этой цели вы можете использовать объект-компаньон:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...