我正在尝试使用一个通用的抽象超类来实现相关类型的树形树(例如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。我在做什么错了吗?
答案 0 :(得分:2)
==
调用Object
的{{1}}方法,而不是您的重载方法。因此,您到处都需要equals(Any?)
。
您的实现将抛出异常,而不是为错误的类型返回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
}
}
在Foo
和Bar
类中。