Дейзи Чейнинг Элвис Операторс?

Это как-то уродливо

override var x1: Double = 0.0 //x-coordinate for object
    get() =
        if(hasParent) { //if there is no parent, we can't have an x coord anyway - nowhere to draw this object
            if (hasPrev) { //we won't always have a previous event, thus the other branch
                prev!!.x2 + parent!!.mEventSpacing
            } else {
                parent!!.mEventStartX
            }
        } else {
            field
        }

Можно ли заменить его чем-то вроде следующего?

override var x1: Double = 0.0
    get() = (prev?.x2 + parent?.mEventSpacing) ?: parent?.mEventStartX ?: field

Логика явно не там, но есть ли что-то близкое к этому? Или для того, чтобы сделать что-то простое, потребуется серьезное вмешательство?

1 ответ

Решение

Предположим, что hasParent = parent != null а также hasPrev = prev != null,
Также предположим, parent а также prev определяются как valне var в if или же when заявления, потому что я не люблю добавлять !! много раз.

Что вы делаете, используя when выражение:

override var x1: Double = 0.0 //x-coordinate for object
    get() = when {
        parent != null && prev != null -> prev.x2 + parent.mEventSpacing
        parent != null && prev == null -> parent.mEventSpacing
        parent == null -> field
    }

Вы можете использовать комбинацию ?. оператор и let функция (см. раздел " Безопасные звонки "):

override var x1: Double = 0.0 //x-coordinate for object
    get() =
        parent?.let { pr -> prev?.let { pv -> pv.x2 + pr.mEventSpacing } ?: pr.mEventSpacing } ?: field

let Функция выполняет блок параметров, параметр которого называется letи вернуть последнее выражение в блоке параметров.

Например, 1.let { it + 2 } является 3,

x?.let выполняет let функционировать, если x не является нулевым т.е. x?.let { ... } такой же как if (x != null) x.let { ... } else null),

Вот,

если parent == null, затем
parent?.let { pr -> prev?.let { pv -> pv.x2 + pr.mEventSpacing } ?: pr.mEventSpacing } просто null,

если parent != null, затем
parent?.let { pr -> prev?.let { pv -> pv.x2 + pr.mEventSpacing } ?: pr.mEventSpacing } такой же как prev?.let { pv -> pv.x2 + parent!!.mEventSpacing } ?: parent!!.mEventSpacing

Вы можете сократить это. если prev == null, затем prev.x2 можно рассматривать как 0, Так

override var x1: Double = 0.0 //x-coordinate for object
    get() =
        parent?.let { pr -> (prev?.let { pv -> pv.x2 } ?: 0) + pr.mEventSpacing } ?: field

Вы можете дополнительно сократить это с помощью it во внутреннем let функция.

override var x1: Double = 0.0 //x-coordinate for object
    get() =
        parent?.let { pr -> (prev?.let { it.x2 } ?: 0) + pr.mEventSpacing } ?: field

Также вы можете использовать комбинацию run а также let, (Google kotlin run или же kotlin run vs let если ты этого не знаешь.)

override var x1: Double = 0.0 //x-coordinate for object
    get() =
        parent?.run { (prev?.let { it.x2 } ?: 0) + mEventSpacing } ?: field

Но я думаю, используя when легче всего понять.


Ну если parent а также prev были определены как var, с помощью when выражение с !! может поднять NPE, в то время как с помощью ?.let, ?.run, а также ?: никогда не будет поднимать NPE в многоядерном устройстве. Чтобы предотвратить это, вы можете определить местный valс текущими значениями в функции получения, так что вам никогда не понадобится использовать !! оператор.

Другие вопросы по тегам