Kotlin惯用的将if.else null用作?./ ?:链的一部分的方式是什么?

时间:2019-05-01 12:08:21

标签: kotlin idiomatic

(为清楚起见而编辑)

我不断发现自己在写(if (x) f() else null) ?: (if (y) g() else null) ?: (if (z) h() else null)和类似的书,而且我确定我不是唯一的人ץ

我一直在追求下面定义的类似valueIf的函数(它是takeIf,参数顺序相反,因此值是惰性的),这会让我编写类似{{1} },而不是像getViewEventType2()这样的代码(均在下面进行详细说明)。

我想念一个成语吗?

(此外,编译器是否对此类功能很聪明,还是我应该担心会创建过多的临时闭包?)

getViewEventType1()

2 个答案:

答案 0 :(得分:3)

您仍然可以使用takeIf()来实现所需的功能,如Intent的扩展功能中所示:

fun Intent.getViewEventType(): String? {
    return takeIf { it.action == "android.intent.action.VIEW" }
        ?.`data`
        ?.pathSegments
        ?.takeIf { it.size == 3 && it[0] == "app" && it[1] == "event" }
        ?.get(2)
}

由OP编辑:这是我所使用的最终代码:

fun getViewEventType(): String? {
    return intent.takeIf { it.action == "android.intent.action.VIEW" }
            ?.`data`
            ?.pathSegments
            ?.takeIf { it.size == 3 && it[0] == "app" && it[1] == "event" }
            ?.get(2)
}

答案 1 :(得分:0)

Wangs answer所示:takeIf是进行此类构造的方法。

我将其余的留给有兴趣的人(正如我的评论已经应用到这里一样):您可能希望省略let,而推荐safe operator ?.。另外,您可能还对destructing declarations感兴趣,因此我认为它更具可读性:

fun Intent.getViewEventType() : String? = takeIf { it.action == "android.intent.action.VIEW" }
        ?.`data`?.pathSegments
        ?.takeIf { it.size == 3 }
        ?.takeIf { (source, actionType) -> // destructuring in action... you may want to name the variables appropriately
            source == "app" && actionType == "event"
        }
        ?.get(2)

我在这里也使用了single expression function,但我留给您使用。由于您在这里进行了大量链接,因此您至少可能希望在使用此类构造时指定返回类型(也可以省略)。