等于重载

问题描述 投票:0回答:3

Kotlin 的 Equals OPERATOR 重载根本不起作用(运算符 '!=' 不能应用于 'SettingString' 和 'String'):

class SettingString(var selected) {
    override infix fun equals(other: Any?) = other is String && selected == other
}
fun arbitraryFunction() {
    val mode = SettingString("Boost")
    mode != "Boost" // error
}
kotlin operator-overloading
3个回答
0
投票

这是设计的

Kotlin 在编译时检查值相等运算符的适用性,并可能拒绝

A
B
的某些类型组合。具体来说,它使用了以下基本原理。

如果

A
的类型和
B
的类型绝对不同且与子类型无关,则
A == B
是无效表达式,应导致编译时错误。

通俗地说:这个原则的意思是“任何两个与子类型无关的对象都不能被

==
认为是相等的”

因为

SettingString
String
是完全独立的、不相关的类型,编译器甚至不会尝试比较它们。这意味着如果你试图像这样隐式地比较两个完全不同的对象,这是一个错误。

你总是可以

equals()
显式,或者使用不同的关键字编写你自己的中缀运算符。如果为了可读性,也可以使用类型别名。一个值/内联类可能会遇到同样的问题,因为它编译成一个新类型(虽然将来可能会改变?)


0
投票

与不是 SettingString 的对象进行比较也需要使用“as Any”进行转换:

class SettingString(private var selected: String) {

  override infix fun equals(other: Any?): Boolean {
    if (other is SettingString) {
      return other == selected
    }
    return other is String && selected == other
  }

  override fun hashCode(): Int {
    return selected.hashCode()
  }

}

val mode = SettingString("Boost")

val other = SettingString("Boost")
mode != other   // This obviously works

val other2 = "Boost"
mode != other2           // Doesn't work
mode != other2 as Any    // This does work
!(mode equals "Boost")   // This does work also

在这里查看讨论:https://discuss.kotlinlang.org/t/overloading-with-different-types-of-operands/4059/17


0
投票

围绕相等运算符有一些编译器魔法——只要

equals()
的实现表现得像他们应该的那样,这就很有意义。

首先,请注意,在这种情况下,您可以按名称调用

equals()
,它将按预期使用您的覆盖方法。

然而,虽然它编译了,但它的行为不正确:你的

equals()
方法没有履行它的合同.

一方面,它不是 自反

a.equals(a)
应该总是返回 true,但是你的方法总是返回 false。

对于另一个,它不是对称

a.equals(b)
应该总是给出与
b.equals(a)
相同的结果,但在你的例子中,
mode.equals("Boost")
返回
true
,而
"Boost".equals(mode)
返回
false
。 (毕竟,系统 String 类对您的代码一无所知。

怎么可能呢?)

不遵守
equals()

合同会导致各种奇怪的问题和意想不到的行为。 (例如,您可能会在集合或映射中获得重复值,或者它们的元素似乎随机消失并重新出现,或者迭代器可能永远不会完成。)

这样的错误可能很难追踪。 一般来说,没有安全的方法允许不同类的对象进行相等比较。(如果您控制两个类及其所有公共超类,有时可以做到这一点,但很难做到正确;参见

this excellent article

所有血腥细节。)

所以当你的 

equals()

方法编译时,恐怕它有致命的缺陷。

因为如果行为良好,不相关的类将永远不会比较相等,Kotlin 编译器使相等运算符 
==
!=
equals() 方法本身更具限制性:如果编译器可以告诉这两个对象不能相关,它甚至阻止你尝试比较它们。它是使语言更安全并防止某些类型的错误的众多 Kotlin 功能之一。

顺便说一句,编译器特殊对待这些运算符应该不足为奇,因为它必须这样做才能允许空参数;

null == something

 是有效的,即使 
null.equals(something)
 不是。

© www.soinside.com 2019 - 2024. All rights reserved.