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

时间:2020-02-28 19:33:50

标签: oop kotlin

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

我有此代码:

interface User {

  val id: String

}

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

interface User {

  val id: String

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

}

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

谢谢

1 个答案:

答案 0 :(得分:3)

不,恐怕不可能。

如果您尝试使用代码,则编译器会抱怨:

'equals' hides member of supertype 'Any' and needs 'override' modifier

如果您添加override修饰符:

An interface may not implement a method of 'Any'

原因有点模糊,并且是从Java继承的(!)。

最初,接口只能包含抽象方法(和常量字段)。当添加了在接口中指定方法实现的功能时,它是在不破坏现有代码的情况下完成的,因此它们仅适用于尚未已经实现的类。 (在Java中,它们被称为“默认”方法来对此进行增强。)如果一个类具有实现(无论是在该类中还是在一个超类中定义),都会使用该实现,而默认值将被忽略。

尽管有一些极端的情况:Object中定义的方法(Java相当于Kotlin的Any)。这些是clone()equals()finalize()getClass()hashCode()notify()notifyAll()toString(),和wait()。 (这些天中大多数都很少直接使用,但是equals()hashCode()toString()当然非常重要。)

由于这些方法是在Object中定义的,因此每个类都有一个直接的实现(来自Object或某些子类)。因此,永远无法使用该接口的默认实现。

对于Kotlin / JVM和Any中定义的相应方法,也完全一样—实际上,如果您尝试提供任何这些方法的默认实现,则编译器会通过给出错误来使其明确。如上所示。

这很遗憾,因为在某些情况下,equals()hashCode()和/或toString()的默认实现会非常有用!但这会带来复杂性,脆弱性和一些令人惊讶的极端情况。有关权威性说明,请参见this answer