Kotlin结合了多个Elvis运算符

时间:2018-07-12 13:12:21

标签: android json kotlin

我正在将Firebase DataSnapshot(json)对象解析为数据类。我可以将它们组合起来,如果其中任何一个为null,则可以返回以下值?像Swift的guard let ..., let ... else { return }

func parse(snapshot: DataSnapshot) {
    val type = snapshot.child("type").value as? String ?: return
    val unitType = UnitEnumType.values().firstOrNull { it.abbrv == type } ?: return
    val imageUrl = snapshot.child("image_url").value as? String ?: return
    ...
}

2 个答案:

答案 0 :(得分:1)

你可以写

val (type, unitType, imageUrl) = Triple(
    snapshot.child("type").value as? String ?: return,
    UnitEnumType.values().firstOrNull { it.abbrv == "a" } ?: return,
    snapshot.child("image_url").value as? String ?: return
)

但是,您不能在第二个表达式中引用type(第一个表达式的结果)。这是一项全有或全无的任务。

答案 1 :(得分:0)

我的意思是,从技术上讲,您可以设置一些疯狂的功能,如下所示:

inline fun <A, R> guardLet(pairA: Pair<A?, (A) -> Boolean>, block: (A) -> R): R? {
    val (a, aPredicate) = pairA
    if(a != null && aPredicate(a)) {
        return block(a)
    }
    return null
}

inline fun <A, B, R> guardLet(pairA: Pair<A?, (A) -> Boolean>, pairB: Pair<B?, (B) -> Boolean>, block: (A, B) -> R): R? {
    val (a, aPredicate) = pairA
    val (b, bPredicate) = pairB
    if(a != null && b != null && aPredicate(a) && bPredicate(b)) {
        return block(a, b)
    }
    return null
}

并命名为

guardLet(someProperty to { it != "blah" }, otherProperty to { it.something() }) { somePropertyByCondition, otherPropertyByCondition ->
    ...
} ?: return

尽管在这种情况下,您可以使用:

inline fun <R, A> ifNotNull(a: A?, block: (A) -> R): R? =
    if (a != null) {
        block(a)
    } else null

inline fun <R, A, B> ifNotNull(a: A?, b: B?, block: (A, B) -> R): R? =
    if (a != null && b != null) {
        block(a, b)
    } else null

inline fun <R, A, B, C> ifNotNull(a: A?, b: B?, c: C?, block: (A, B, C) -> R): R? =
    if (a != null && b != null && c != null) {
        block(a, b, c)
    } else null

inline fun <R, A, B, C, D> ifNotNull(a: A?, b: B?, c: C?, d: D?, block: (A, B, C, D) -> R): R? =
    if (a != null && b != null && c != null && d != null) {
        block(a, b, c, d)
    } else null

然后随便

ifNotNull(
    snapshot.child("type").value as? String,
    UnitEnumType.values().firstOrNull { it.abbrv == type },
    snapshot.child("image_url").value as? String) { type, unitType, imageUrl -> 
    ...
} ?: return

我不知道,我只是向你扔了可能性。