是否可以在 Kotlin 接口中编写 equals 方法的默认实现?

Héc*_*tor 7 oop kotlin

是否可以equals在 Kotlin 接口中编写方法的默认实现?

我有这个代码:

interface User {

  val id: String

}
Run Code Online (Sandbox Code Playgroud)

我希望所有实现 User 的类都使用id属性进行比较。像这样的东西:

interface User {

  val id: String

  fun equals(other: Any?) : Boolean {
    //check type and stuff
    return id == other.id
  }

}
Run Code Online (Sandbox Code Playgroud)

我知道我可以(也许应该)使用抽象类,但我现在必须处理这种情况。

谢谢

gid*_*dds 8

不,恐怕这是不可能的。

\n\n

如果您尝试您的代码,编译器会抱怨:

\n\n

\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\'equals\' hides member of supertype \'Any\' and needs \'override\' modifier

\n\n

如果添加override修饰符:

\n\n

\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0An interface may not implement a method of \'Any\'

\n\n

原因有点晦涩,是从 Java 继承的(!)。

\n\n

最初,接口只能包含抽象方法(和常量字段)。\xc2\xa0 当添加在接口中指定方法实现的功能时,这样做是为了不破坏现有代码,因此它们仅适用于类还没有实现。\xc2\xa0 (在 Java 中,它们被称为 \xe2\x80\x98default\xe2\x80\x99 方法来强化这一点。)\xc2\xa0 如果一个类有一个实现,无论是在类中还是在超类中定义,都会使用它,并且默认值将被忽略。

\n\n

不过,有一些极端情况:Object中定义的方法(Java 相当于 Kotlin 的Any)。\xc2\xa0 这些方法是clone()equals()Finalize()getClass()hashCode()notify()notifyAll()toString()wait() .\xc2\xa0 (其中大多数现在很少直接使用,但当然equals()hashCode()、 和toString()非常重要。)

\n\n

因为这些方法是在 中定义的Object,所以每个类都有它们的直接实现(来自Object或某个子类)。\xc2\xa0 因此永远不能使用接口的默认实现。

\n\n

事实上,这同样适用于 Kotlin/JVM 以及Any\xe2\x80\x94 中定义的相应方法,如果您尝试提供任何这些方法的默认实现,编译器会通过给出错误来明确它,如上所示。

\n\n

这是一种耻辱,因为在某些情况下,默认实现equals()hashCode()和/或toString()会非常有用!\xc2\xa0 但它会带来复杂性、脆弱性和一些令人惊讶的极端情况;看这个答案有权威的解释。

\n