我正在阅读Scala编程.它说:
您可以
==
通过重写equals
方法来重新定义新类型的行为,该方法始终从类继承Any
.equals
除非被覆盖,否则生成的继承是对象标识,就像Java中的情况一样.所以equals
(和它一起==
)默认情况下是相同的eq
,但你可以通过覆盖equals
你定义的类中的方法来改变它的行为.不可能==
直接覆盖,因为它被定义为类中的最终方法Any
.也就是说,Scala==
在课堂上将其视为如下定义Any
:Run Code Online (Sandbox Code Playgroud)final def == (that: Any): Boolean = if (null eq this) (null eq that) else (this equals that)
但这并不是我在scala 2.9.1中看到的内容,它看起来像:
==
似乎没有默认 equals
==
直接覆盖(没有编译器的抱怨,override
不需要).所以在我看来似乎要么:
我做错了 - 这个Rational
给出的定义
% scala
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29).
Type in expressions to have them evaluated.
Type :help for more information.
scala> Rational(1) == Rational(1)
res0: Boolean = false
scala> Rational(1) equals Rational(1)
res1: Boolean = true
Run Code Online (Sandbox Code Playgroud)或者我正在阅读这本书的过时版本,事情已经发生了变化.
这是怎么回事?
Rex*_*err 21
您正在犯一个非常容易理解的错误 - 您正在尝试编写类型安全等于(即def equals(r: Rational)
)而不是通用等号(即override def equals(a: Any)
).
所以不要覆盖equals
- 注意你不需要override
关键字! - 你是通过重载类型参数创建另一个方法,然后有两个等于方法,一个采取Rational
,一个采取Any
.同样的事情==
; 只有Any
-parameterized方法不能被覆盖.
要获得与Java(和Scala库)一致的行为,您需要将equals重写为类似的东西
override def equals(a: Any) = a match {
case r: Rational => numer == r.numer && denom == r.demon
case _ => false
}
Run Code Online (Sandbox Code Playgroud)