Scala 简单代码上的类强制转换异常(“重写”)

Scala 简单代码上的类强制转换异常(“重写”),scala,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 我知道我做错了什么,但我不明白是什么 编辑 我通过更改以下内容修改了代码: c

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

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中以交互方式更改了类,导致了奇怪的结果。从零开始,它是有效的。还是第一个…

从不重写
=
操作符,它由scala编译器提供,语义类似于java中的Object.equals方法。这就是它总是返回布尔值的原因。因此,我假设当您实现自己的运算符时,scala尝试将其结果转换为布尔值。

从不重写
=
运算符,它由scala编译器提供,语义类似于java中的Object.equals方法。这就是它总是返回布尔值的原因。因此,我假设当您实现自己的运算符时,scala尝试将其结果强制转换为布尔值。

更新的版本(返回布尔值的
=
)对我适用

出现奇怪错误的原因可能是,您在REPL中尝试了它,并重新定义了
第一个
类,而不是
第二个

REPL做了一些诡计,允许您重新定义类和变量,这在scala中通常是不可能的,因此您基本上得到了两个版本的
First
,并且您的
Second
定义仍然引用旧的定义,而您发送给构造函数的定义使用
new First()
是新的-因此不匹配

只要重新定义
第二个
类,它就会工作

顺便说一句,重新定义
==
没有太大的错误,但是在这些情况下更常见的是重写
等于,这将产生相同的效果。
=
的默认实现只调用
equals
,因此,它的一个问题是下游的某个用户可能会在您的一个子类中重写
equals
,并且由于它没有达到预期的效果而被难倒。

更新的版本(返回布尔值的
=
对我有效

出现奇怪错误的原因可能是,您在REPL中尝试了它,并重新定义了
第一个
类,而不是
第二个

REPL做了一些诡计,允许您重新定义类和变量,这在scala中通常是不可能的,因此您基本上得到了两个版本的
First
,并且您的
Second
定义仍然引用旧的定义,而您发送给构造函数的定义使用
new First()
是新的-因此不匹配

只要重新定义
第二个
类,它就会工作


顺便说一句,重新定义
==
没有太大的错误,但是在这些情况下更常见的是重写
等于,这将产生相同的效果。
==
的默认实现只调用
equals
,因此,它的一个问题是下游用户可能会在您的一个子类中重写
equals
,因为
Second
是一个case类,它没有定义或继承自定义的
equals
方法,所以为
Second\equals
生成的代码应该是

override def equals(x: Any): Boolean = x match {
  case x: Second => first == x.first
  case _ => false
}
第一个分支中的
=
将是您的
==(第一个)
,而不是通常的
==(任何)
,因为它是更具体的重载。因此,在声明
Second
时,您“应该”得到一个编译错误


但是从堆栈跟踪来看,编译器似乎在某个地方插入了强制转换,要么是
(x匹配…).asInstanceOf[Boolean]
,要么是
(first==x.first)。asInstanceOf[Boolean]
。老实说,我真的想不出这样写的原因。但是这会导致
Second
编译,并且您以后的调用会失败。

因为
Second
是一个case类,并且它没有定义或继承自定义的
equals
方法,所以为
Second#equals
生成的代码应该如下

override def equals(x: Any): Boolean = x match {
  case x: Second => first == x.first
  case _ => false
}
第一个分支中的
=
将是您的
==(第一个)
,而不是通常的
==(任何)
,因为它是更具体的重载。因此,在声明
Second
时,您“应该”得到一个编译错误


但是从堆栈跟踪来看,编译器似乎在某个地方插入了强制转换,要么是
(x匹配…).asInstanceOf[Boolean]
,要么是
(first==x.first)。asInstanceOf[Boolean]
。老实说,我真的想不出这样写的原因。但是这会使
第二次编译,而您以后的调用会失败。

我理解您的答案,但仍然觉得结果出乎意料。在实际案例中,我们已经通过使用不同的方法解决了这个问题,但这个例外仍然让我感到惊讶。谢谢,我正在用repl测试它,以便更好地理解,但我还是有点糊涂:)我理解你的答案,但我仍然觉得结果出乎意料。在实际案例中,我们已经通过使用不同的方法解决了这个问题,但这个例外仍然让我感到惊讶。谢谢,我正在用repl对它进行内联测试,以便更好地理解它,但我还是有点不知所措:)是的,这个问题是由我在repl中以交互方式更改它引起的。从零开始,它是有效的。thnksOverriding equals而不是==有效,但是如果==调用等于为什么我的示例失败?1。这不是重新定义或覆盖
==
,而是重载。2.重写
==
的另一个问题是,当左侧为
null
@AlexeyRomanov(1)是的,它不再工作!(我想知道为什么它会让我