首页 文章

比较Kotlin中的两个选项

提问于
浏览
0

考虑一个id字段的类,该字段在存储在数据库中之前可能为null:

class IdableK<T : IdableK<T>> : Comparable<T> {    
    private var id : Long? = null
}

我正在尝试实现 compareTo 方法如下:

override fun compareTo(other: T): Int {
        if (id == null) {
            return -1;
        }

        if (other.id == null) {
            return 1;
        }

        return id!!.compareTo(other.id!!)
    }

这是一种正确的做法吗?有一个简单的方法吗?

3 回答

  • 1

    看看kotlin.comparisons package . 例如你可以使用compareValues

    class IdableK<T : IdableK<T>> : Comparable<T> {
        private var id: Long? = null
    
        override fun compareTo(other: T) = compareValues(id, other.id)
    }
    
  • 6

    这是不正确的 . 如果你有两个实例,其id设置为 null ,当你对它们调用 compareTo(other) 时,两个实例都将返回 -1 ,而如果一个实例返回 -1 ,则另一个实例将返回 1 . 我不确定是否有可能基于可空属性实现 compareTo 是有意义的,但我也可以't imagine any. Maybe there'更好的方式吗?

    此外,您应该避免非空断言( !! ) . 由于您正在使用 var ,因此其他线程可能会将该值更改为null,这样即使您之前执行了空检查,该值现在为null并且 !! 抛出 . 相反,您应该将两个ID存储在局部变量中,并检查这些值是否为 null 值 .

    如果你绝对必须使用 compareTo ,我会这样做:

    override fun compareTo(other: T): Int {
        val thisId = id
        val otherId = other.id
        if (thisId == null && otherId == null) return 0
        if (thisId == null && otherId != null) return -1
        if (thisId != null && otherId == null) return 1
    
        // thisId and otherId are now smart cast to Long
        return thisId.compareTo(otherId)
    }
    
  • 0

    这是一个简单的方法:

    override fun compareTo(other: T) :Int {
        return id?.compareTo(other.id ?: return 1) ?: -1
    }
    

    然而,这段代码对新手kotlin程序员来说非常不友好 . 它涉及太多的魔法,使它看起来像scala . 这三个问号让人感到困惑,至少他们必须思考一两分钟才能意识到这个简约的单行内容正在发生什么 . 我还是喜欢你的版本 . 它更冗长,但更清晰 .

    而且我只是一个设计问题 . 如果你不是这个编程难题 . 它只是 override fun compareTo(other: T) = id.compareTo(other.id) . 简单,清晰,没有误导性 .

    我宁愿扔掉所有的空检查代码,只是忍受那些空的断言 . 因为在完全初始化之前,你不会比较那些东西 . 如果这些断言失败,则意味着发生了非常糟糕的事情 .

    哦,顺便说一句,我不知道你的项目,如果它遇到了你必须比较可空属性的罕见情况,我想你可以写一个特殊版本的 Comparator ,考虑空值而不是抛出NPE . 不要乱用自然秩序 .

相关问题