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

如何为Kotlin中的相关子类型实现equals(),kotlin,equality,Kotlin,Equality,我试图用一个公共抽象超类实现一个相关类型的类树(例如,AST节点)。我试图在子节点上实现equals(),这样不同的子类型确实是不同的,但是两个相似的类型可以进行更内省的相等计算。我试过这个: abstract class Something { abstract fun equals(other:Something) : Boolean } class Foo(val value:Int):Something() { override fun equals(other:So

我试图用一个公共抽象超类实现一个相关类型的类树(例如,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
}
抽象类{
抽象乐趣等于(其他:某物):布尔值
}
类Foo(val值:Int):Something(){
覆盖乐趣等于(其他:某物):布尔值{
返回值(其他为Foo)。值==值
}
}
类栏(val值:Int):Something(){
覆盖乐趣等于(其他:某物):布尔值{
返回值(其他为条形图)。值==值
}
}
趣味主线(args:Array){
val foo1:Something=Foo(1)//如果我不将它们作为抽象类型键入
val foo2:Something=Foo(1)//那么我甚至不让我检查它
val bar1:Something=Bar(42)//如果bar1==foo1,因为它们是推断出来的
val bar2:Something=Bar(42)//作为不同的类型
println(“foo1==foo2${foo1==foo2}”)//应打印为true
println(“bar1==bar2${bar1==bar2}”)//应打印为true
println(“foo1==bar1${foo1==bar2}”)//应该打印false
}
不幸的是,所有的
println
都显示为false。我做错了什么?错了

  • =
    调用
    对象的
    equals(Any?
    方法,而不是重载。因此,您需要在任何地方使用
    覆盖操作符fun equals(其他:Any?

  • 对于错误的类型,您的实现将抛出异常而不是返回
    false
    ,这很糟糕。相反,你需要

    // in Foo
    override fun equals(other: Any?) : Boolean = when (other) {
        is Foo -> other.value == value
        else -> false
    }
    
  • =
    调用
    对象的
    equals(Any?
    方法,而不是重载。因此,您需要在任何地方使用
    覆盖操作符fun equals(其他:Any?

  • 对于错误的类型,您的实现将抛出异常而不是返回
    false
    ,这很糟糕。相反,你需要

    // in Foo
    override fun equals(other: Any?) : Boolean = when (other) {
        is Foo -> other.value == value
        else -> false
    }
    

  • 如果希望
    =
    正常工作,则必须重写
    运算符fun equals(其他:任何?):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
        }
    }
    

    如果希望
    =
    正常工作,则必须重写
    运算符fun equals(其他:任何?):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 
    
    属于类
    任何
    ,而不是您的自定义equals实现

    您需要使用语法
    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
    类中。

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

    open operator fun equals(other: Any?): Boolean 
    
    属于类
    任何
    ,而不是您的自定义equals实现

    您需要使用语法
    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
    课程中。

    附带问题。。是否有理由更喜欢when表达式而不仅仅是
    other is Foo&&other.value==value
    ?(我很惊讶这实际上是可行的;我一直忘记了“一旦你测试它,我们就可以对它做一些编译器愿意做的假设,作为副作用”)不,我更喜欢那个版本,我只是没有考虑它。附带问题..有没有理由更喜欢when表达式而不仅仅是
    other是Foo&&other.value==value
    ?(我很惊讶这实际上是可行的;我一直忘了“一旦你测试了它,我们就可以对它做一些假设,这是编译器愿意做的副作用)不,我更喜欢那个版本,我只是没有考虑它。