Kotlin 接口实现打破了“等于”覆盖
Kotlin interface implementation breaks `equals` overriding
我有以下 class 作为其他一些 classes 的基础:
abstract class BaseFitness: Comparable<BaseFitness> {
var valid: Boolean = false
fun invalidate() { valid = false }
abstract fun value(): Double
abstract fun copy(): BaseFitness
override operator fun equals(other: Any?): Boolean =
if (other is BaseFitness)
this.value() == other.value()
else
throw IllegalArgumentException("Can only compare to another class derived from BaseFitness.")
override fun compareTo(other: BaseFitness): Int =
this.value().minus(other.value())
.let { if (it.isNaN()) 0.0 else it }
.sign.toInt()
@JvmName("compareToOperator")
operator fun compareTo(other: Any?): Int =
if (other is BaseFitness)
this.compareTo(other)
else
throw IllegalArgumentException("Can only compare to another class derived from BaseFitness.")
}
现在,在这个 class 中,我想实现基本的比较行为。
基本上我希望能够做到:
if (fit1 == fit2) { /* do stuff */ }
if (fit1 > fit2) { /* do stuff */ }
if (fit1 < fit2) { /* do stuff */ }
myFitnessSequence.max()
equals()
和 compareTo()
运算符函数负责前 3 项。然而,对于最后一项,我需要 BaseFitness
来实现 Comparable
。问题是,当我实现可比较并添加非运算符 compareTo()
方法时,equals()
以某种方式中断并显示此消息:
'operator' modifier is inapplicable on this function: must override ''equals()'' in Any
我尝试做与 compareTo()
相同的事情,只是有 2 个 equals()
的实现,一个被标记为运算符,一个被标记为方法,并将 @JvmName
添加到其中之一,我得到
'@JvmName' annotation is not applicable to this declaration
现在我的选择基本上是要么选择保留 ==
运算符但不实施 Comparable
要么放弃 ==
使用 comparable.
您不需要用 operator
关键字标记 equals
和 compareTo
,它们都已在各自的类型中定义为运算符。
在 equals
的情况下,Any
将其定义为 operator
并且 compareTo
在 Comparable
interface
中标记为 operator
.
所以您所要做的就是通过覆盖它们来提供它们的实现。
Regarding the equals method
The equals function is marked as override, because, unlike other
conventions, the method implementing it is defined in the Any class
(equality comparison is supported for all objects in Kotlin). That
also explains why you don’t need to mark it as operator: the base
method in Any is marked as such, and the operator modifier on a method
applies also to all methods that implement or override it.
Regarding the Comparable interface
Kotlin supports the same Comparable interface. But the compareTo
method defined in that interface can be called by convention, and uses
of comparison operators ('<',
'>', <=, and >=) are translated into calls of compareTo.
我有以下 class 作为其他一些 classes 的基础:
abstract class BaseFitness: Comparable<BaseFitness> {
var valid: Boolean = false
fun invalidate() { valid = false }
abstract fun value(): Double
abstract fun copy(): BaseFitness
override operator fun equals(other: Any?): Boolean =
if (other is BaseFitness)
this.value() == other.value()
else
throw IllegalArgumentException("Can only compare to another class derived from BaseFitness.")
override fun compareTo(other: BaseFitness): Int =
this.value().minus(other.value())
.let { if (it.isNaN()) 0.0 else it }
.sign.toInt()
@JvmName("compareToOperator")
operator fun compareTo(other: Any?): Int =
if (other is BaseFitness)
this.compareTo(other)
else
throw IllegalArgumentException("Can only compare to another class derived from BaseFitness.")
}
现在,在这个 class 中,我想实现基本的比较行为。
基本上我希望能够做到:
if (fit1 == fit2) { /* do stuff */ }
if (fit1 > fit2) { /* do stuff */ }
if (fit1 < fit2) { /* do stuff */ }
myFitnessSequence.max()
equals()
和 compareTo()
运算符函数负责前 3 项。然而,对于最后一项,我需要 BaseFitness
来实现 Comparable
。问题是,当我实现可比较并添加非运算符 compareTo()
方法时,equals()
以某种方式中断并显示此消息:
'operator' modifier is inapplicable on this function: must override ''equals()'' in Any
我尝试做与 compareTo()
相同的事情,只是有 2 个 equals()
的实现,一个被标记为运算符,一个被标记为方法,并将 @JvmName
添加到其中之一,我得到
'@JvmName' annotation is not applicable to this declaration
现在我的选择基本上是要么选择保留 ==
运算符但不实施 Comparable
要么放弃 ==
使用 comparable.
您不需要用 operator
关键字标记 equals
和 compareTo
,它们都已在各自的类型中定义为运算符。
在 equals
的情况下,Any
将其定义为 operator
并且 compareTo
在 Comparable
interface
中标记为 operator
.
所以您所要做的就是通过覆盖它们来提供它们的实现。
Regarding the equals method
The equals function is marked as override, because, unlike other conventions, the method implementing it is defined in the Any class (equality comparison is supported for all objects in Kotlin). That also explains why you don’t need to mark it as operator: the base method in Any is marked as such, and the operator modifier on a method applies also to all methods that implement or override it.
Regarding the Comparable interface
Kotlin supports the same Comparable interface. But the compareTo method defined in that interface can be called by convention, and uses of comparison operators ('<', '>', <=, and >=) are translated into calls of compareTo.