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)是的,它不再工作!(我想知道为什么它会让我