菊花链猫王运算符?

时间:2018-07-26 04:08:13

标签: kotlin nullable kotlin-null-safety

这有点难看:

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 个答案:

答案 0 :(得分:1)

假设hasParent = parent != nullhasPrev = prev != null
还假设parentprev语句中的valvar被定义为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函数(请参阅Safe Calls部分):

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不为null,则

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

此外,您可以结合使用runlet。 (如果您不知道,请使用Google kotlin runkotlin run vs let。)

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

但是我认为使用when是最容易理解的东西。


好吧,如果将parentprev定义为var,则将when的{​​{1}}表达式与!!一起使用会产生NPE,而使用{{1} },?.let?.run永远不会在多核设备中引发NPE。为避免这种情况,您可以在getter函数中使用当前值定义本地?:,这样您就无需使用val运算符。