这是我们的应用程序中发生的事情的简化代码:
class First { def ==(first:First)= "mystring"}
case class Second(first:First)
Second(new First) == Second(new First)
这给: java.lang.ClassCastException:java.lang.String无法强制转换为java.lang.Boolean
我知道我做错了什么,但我不明白。
修改
我修改了代码:
class First { def ==(first:First)= true}
现在REPL中的错误是:
error: type mismatch;
found : First(in object $iw)
required: First(in object $iw)
Second(new First) == Second(new First)
对我来说更加出乎意料:\
更新第二个例子是我的错。我在REPL中以交互方式更改了类First,导致奇怪的结果。从头开始它有效。还是第一个......
答案 0 :(得分:3)
更新版本(==
返回布尔值)适用于我。
你的奇怪错误的原因可能是因为你在REPL中尝试它,并重新定义了First
类,但没有Second
。
REPL做了一些技巧,允许你重新定义类和变量,这在scala中通常是不可能的,所以你基本上最终有两个版本的First
,而你的Second
定义仍然引用旧的一,你用new First()
发送给构造函数的那个是新的 - 因此不匹配。
再次重新定义Second
课程,它会起作用。
重新定义==
BTW没有太大问题,但在这些情况下覆盖equals
更常见,这会产生相同的效果。 ==
的默认实现只调用equals
,因此,它的一个问题是下游的某个人可能会覆盖您的某个子类中的equals
,并且会被它不支持的事实所困扰做他们所期望的。
答案 1 :(得分:2)
永远不要覆盖scala编译器提供的==
运算符,其语义类似于java中的Object.equals方法。这就是它总是返回布尔值的原因。因此,我假设当您实现自己的运算符时,scala会尝试将其结果转换为布尔值。
答案 2 :(得分:1)
由于Second
是案例类,并且未定义或继承自定义equals
方法,因此生成的Second#equals
代码应如下所示
override def equals(x: Any): Boolean = x match {
case x: Second => first == x.first
case _ => false
}
第一个分支中的==
将是您的==(First)
,而不是通常的==(Any)
,因为它是更具体的重载。因此,在声明Second
时,您“应该”收到编译错误。
但是从堆栈跟踪看来,编译器似乎在某处插入了一个强制转换,(x match ...).asInstanceOf[Boolean]
或(first == x.first).asInstanceOf[Boolean]
。说实话,我真的不能想到为什么会这样写的原因。但这会使Second
编译,后来的调用失败。