如何在 Kotlin 中为相关子类型实现 equals()
How to implement equals() for related subtypes in Kotlin
我正在尝试使用通用抽象超级 class 实现相关类型(例如 AST 节点)的 class 树。我正在尝试在子节点上实现 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
都只是显示错误。我做错了什么?错了?
==
调用 Object
的 equals(Any?)
方法,而不是您的重载。所以你需要到处都有 override operator fun equals(other: Any?)
。
对于错误的类型,您的实现将抛出异常而不是返回 false
,这很糟糕。相反,你需要
// in Foo
override fun equals(other: Any?) : Boolean = when (other) {
is Foo -> other.value == value
else -> false
}
如果你想让==
正常工作,你必须覆盖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
}
}
当您使用语法 foo1 == foo2
Kotlin 调用函数时:
open operator fun equals(other: Any?): Boolean
的 class 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
class 中。
我正在尝试使用通用抽象超级 class 实现相关类型(例如 AST 节点)的 class 树。我正在尝试在子节点上实现 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
都只是显示错误。我做错了什么?错了?
==
调用Object
的equals(Any?)
方法,而不是您的重载。所以你需要到处都有override operator fun equals(other: Any?)
。对于错误的类型,您的实现将抛出异常而不是返回
false
,这很糟糕。相反,你需要// in Foo override fun equals(other: Any?) : Boolean = when (other) { is Foo -> other.value == value else -> false }
如果你想让==
正常工作,你必须覆盖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
}
}
当您使用语法 foo1 == foo2
Kotlin 调用函数时:
open operator fun equals(other: Any?): Boolean
的 class 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
class 中。