是否可以在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
}
}
我知道我可以(也许应该)使用抽象类,但是我现在必须处理这种情况。
谢谢
答案 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。