Kotlin中的压倒性平等

时间:2018-10-15 10:53:10

标签: kotlin

CS实现kotlin.CharSequence。它的本质在这里:

class CS  (val sequence: CharSequence = "") : CharSequence {
... override get/length in interface CharSequence 
    override fun equals(other: Any?): Boolean =
            (this === other) || ((other is String) && this.sequence.equals(other))
}

CS("hello") == "hello"的编译器对象为:运算符'=='不能应用于'CS'和'String'CS("hello") == "hello" as AnyCS("hello").equals("hello")都没有问题。

我在做什么错了?

3 个答案:

答案 0 :(得分:2)

如果操作两侧的类型已知并且彼此不同,则Kotlin中的==运算符将不起作用。
例如:

3 == "Hello"
true == 5.0
// and so on

将给出编译错误,因为编译器会推断操作数是不同类的实例,因此不能相等。

唯一的例外是,如果运算符的一侧是另一侧的子类:

open class A
class B: A()
class C: A()

val c = C()
val b = B()
val a = A()

c == b
c == a // good
a == b // also good

在这种情况下,c == b将给出编译错误,而其他两个操作则不会。

这就是为什么当您将操作的一侧强制转换为Any时,由于所有内容都是Any的子类型,因此不再给出错误的原因。

答案 1 :(得分:1)

我不确定导致此错误的原因,但可能与您的方法存在更深层次的问题有关……

在Kotlin(和Java)中,equals()方法的规范非常严格。一个条件是它必须是对称的:只要ab不为空,a.equals(b)必须始终提供与b.equals(a)相同的结果。

但是您的实现未能通过此测试,因为CS("abc").equals("abc")返回true,而"abc".equals(CS("ABC"))false。那是因为您的班级了解CharSequence,例如String,但是String不知道您的班级。

没有简单的方法可以解决此问题。通常,允许一个类的实例仅等于该类的实例要安全得多。如果您同时控制这两个类,那么有很多解决方法,但是它们非常微妙并且涉及很多。 (也许最好的解释是用Martin Odersky et al。)

因此equals()的大多数实现都倾向于遵循以下原则:

override fun equals(other: Any?)
    = (other is ThisClass)
    && field1 == other.field1
    && field2 == other.field2
    // ...

正如我所说,我不知道为什么Kotlin编译器在您的情况下抱怨。可能是发现了此问题的一部分,也可能是无关的。但是我不认为您将能够以平等检查可以完成您想要的方式来修正程序,所以也许最好以此为线索来尝试稍微不同的方法!

答案 2 :(得分:0)

@Michael在评论中提到此运算符有效,因此您可以转到下面的答案:

我认为,您得到的错误可能与Kotlin在推断数据类型时遇到问题有关。您将提供Any类型作为equals(...)方法的参数,并将其与您的类(this)进行比较。也许尝试像这样转换类型:

this == (other as String)

this == (other as CharSequence)

我不确定这是否是正确的方法,但也许会对您有所提示。