Kotlin 结合多个 elvis 算子

Posted

技术标签:

【中文标题】Kotlin 结合多个 elvis 算子【英文标题】:Kotlin combine multiple elvis operator 【发布时间】:2018-12-20 17:51:48 【问题描述】:

我正在将 Firebase DataSnapshot (json) 对象解析为数据类。如果其中任何一个为空,我可以将它们组合起来并返回,而不是以下内容?类似于 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
    ...

【问题讨论】:

Multiple variable let in Kotlin的可能重复 这是真实的示例还是只是一些伪代码?因为它什么都不做(分配在构造函数结束时被丢弃的局部属性)。就我个人而言,我会throw IllegalArgumentException() 而不是在中间返回构造函数并使对象处于未定义状态。这会让你抓住它,你就会知道为什么无法创建对象。 @Pawel,已编辑,无所谓,我只是想知道如何组合连续的elvis算子。 【参考方案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(第一个表达式的结果)。这是一个孤注一掷的任务。

【讨论】:

如果任何一个表达式返回,那么三元组的值将只是 null? 不,你的函数会立即返回。这就是?: return 的意思。【参考方案2】:

我的意思是从技术上讲,你可以像这样设置一些疯狂的功能:

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

我不知道,我只是在向你抛出各种可能性。

【讨论】:

以上是关于Kotlin 结合多个 elvis 算子的主要内容,如果未能解决你的问题,请参考以下文章

学习干货最新Android Kotlin入门教程指南,2023最新!

android RecyclerView pinch zoom,ScaleGestureDetector&GridLayoutManager,with BigImageViewer,kotli

Kotlin初识Kotlin

全新升级 Kotlin系统入门与进阶

谷歌:选用Kotlin的五大理由

Android为什么要从Java改用Kotlin