简单代码上的类强制转换异常(" =="覆盖)

时间:2017-10-05 09:38:48

标签: scala

这是我们的应用程序中发生的事情的简化代码:

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,导致奇怪的结果。从头开始它有效。还是第一个......

3 个答案:

答案 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编译,后来的调用失败。