如何在Kotlin中为相关子类型实现equals()

时间:2018-07-12 18:55:54

标签: kotlin equality

我正在尝试使用一个通用的抽象超类来实现相关类型的树形树(例如AST节点)。我正在尝试在子节点上实现equals(),以使不同的子类型确实有所不同,但是两个类似的类型可以进行更内省的相等性计算。我已经尝试过:

abstract class Something {
    abstract fun equals(other:Something) : Boolean 
}

class Foo(val value:Int):Something() {
    override fun equals(other:Something) : Boolean {
        return (other as Foo).value == value
    }
}

class Bar(val value:Int):Something() {
    override fun equals(other:Something) : Boolean {
        return (other as Bar).value == value
    }
}

fun main(args: Array<String>) {
    val foo1:Something = Foo(1)  // if i don't type these as the abstract type
    val foo2:Something = Foo(1)  // then I it won't even let me check
    val bar1:Something = Bar(42) // if bar1 == foo1, because they're inferred
    val bar2:Something = Bar(42) // as different types
    println("foo1 == foo2 ${foo1 == foo2}") // should print true
    println("bar1 == bar2 ${bar1 == bar2}") // should print true
    println("foo1 == bar1 ${foo1 == bar2}") // should print false
}

不幸的是,所有println都显示为false。我在做什么错了吗?

3 个答案:

答案 0 :(得分:2)

  1. ==调用Object的{​​{1}}方法,而不是您的重载方法。因此,您到处都需要equals(Any?)

  2. 您的实现将抛出异常,而不是为错误的类型返回override operator fun equals(other: Any?),这很糟糕。相反,您需要

    false

答案 1 :(得分:2)

如果您希望==正常工作,则必须覆盖operator fun equals(other: Any?) : Boolean

如果您想显式地要求在子类中实现,那么请不要忘记它,可以在超类中将其标记为abstract

abstract class Something {
    abstract override operator fun equals(other: Any?) : Boolean
}

class Foo(val value:Int):Something() {
    override fun equals(other: Any?): Boolean {
        return (other as Foo).value == value
    }
}

class Bar(val value:Int):Something() {
    override fun equals(other: Any?): Boolean {
        return (other as Bar).value == value
    }
}

答案 2 :(得分:1)

使用语法foo1 == foo2时Kotlin会调用函数:

open operator fun equals(other: Any?): Boolean 
Any类的

,而不是您的自定义等于实现。

您需要使用语法foo1.equals(foo2)来完成所需的操作。另外,就像阿列克谢·罗曼诺夫(Alexey Romanov)在他的回答中指出的那样,您不能将Foo转换为Bar,反之亦然,您需要这样做:

override fun equals(other:Something) : Boolean {
        return when(other) {
         is Foo -> other.value == value
         is Bar -> other.value == value
         else false
        }
    }

FooBar类中。