多重继承、集合和 hashCode/equals 重写
下面的代码生成:
名称的 hashCode
名称的 hashCode
名字等于
ID=0
import scala.collection.mutable
object TestTraits {
def main(args: Array[String]): Unit = {
val toto0 = new Person(0,"toto")
val toto1 = new Person(1,"toto")
val peoples = mutable.Set.empty[PersonID]
peoples.add(toto0)
peoples.add(toto1)
peoples.foreach(_.showID)
//peoples.foreach(_.saySomething)//won't compile'
}
}
trait Name{
var theName=""
override def hashCode(): Int = {
println("Name's hashCode")
var hash = 5;
hash = 71 * hash + this.theName.##;
hash
//super.hashCode()//infinite loop
}
override def equals(that: Any): Boolean = {
println("Name's equals")
that match {
case that: Name => this.theName.equals(that.theName)
case _ => false
}
}
}
abstract class PersonID{
val idNumber: Int
override def hashCode(): Int = {
println("PersonID's hashCode")
super.##
}
override def equals(that: Any): Boolean = {
println("PersonID's equals")
that match {
case that: PersonID => this.eq(that)
case _ => false
}
}
def showID: Unit = {
println("ID=" + idNumber)
}
}
class Person(val id:Int, val s:String) extends {
val idNumber=id
} with PersonID with Name {
/*override def hashCode(): Int = {
println("Person's hashCode")
super.## //infinite loop !!
}
override def equals(that: Any): Boolean = {
println("Person's equals")
that match {
case that: Person => this.eq(that)
case _ => false
}
}*/
theName=s
def saySomething: Unit = {
print("Hello, my name is " + theName + ", ")
showID
}
}
由于“peoples”是一组 PersonID,我期待以下输出:
PersonID 的 hashCode
PersonID 的 hashCode
ID=0
ID=1
有人可以解释这种行为以及如何做我所期望的事情(也就是说,有一个基于字段值的“等于”类,除非将实例放入 Set[PersonID] 中)
另一个谜团是为什么我当我在自定义 hashCode 中使用 super.hashCode() 时会出现无限循环吗?
PS:我使用预初始化的抽象成员,因为我在实际用例中需要它......
The code below generates:
Name's hashCode
Name's hashCode
Name's equals
ID=0
import scala.collection.mutable
object TestTraits {
def main(args: Array[String]): Unit = {
val toto0 = new Person(0,"toto")
val toto1 = new Person(1,"toto")
val peoples = mutable.Set.empty[PersonID]
peoples.add(toto0)
peoples.add(toto1)
peoples.foreach(_.showID)
//peoples.foreach(_.saySomething)//won't compile'
}
}
trait Name{
var theName=""
override def hashCode(): Int = {
println("Name's hashCode")
var hash = 5;
hash = 71 * hash + this.theName.##;
hash
//super.hashCode()//infinite loop
}
override def equals(that: Any): Boolean = {
println("Name's equals")
that match {
case that: Name => this.theName.equals(that.theName)
case _ => false
}
}
}
abstract class PersonID{
val idNumber: Int
override def hashCode(): Int = {
println("PersonID's hashCode")
super.##
}
override def equals(that: Any): Boolean = {
println("PersonID's equals")
that match {
case that: PersonID => this.eq(that)
case _ => false
}
}
def showID: Unit = {
println("ID=" + idNumber)
}
}
class Person(val id:Int, val s:String) extends {
val idNumber=id
} with PersonID with Name {
/*override def hashCode(): Int = {
println("Person's hashCode")
super.## //infinite loop !!
}
override def equals(that: Any): Boolean = {
println("Person's equals")
that match {
case that: Person => this.eq(that)
case _ => false
}
}*/
theName=s
def saySomething: Unit = {
print("Hello, my name is " + theName + ", ")
showID
}
}
Since "peoples" is a set of PersonID, I was expecting the following output:
PersonID's hashCode
PersonID's hashCode
ID=0
ID=1
Does someone can explain this behavior and how to do what I expected (that is, to have a class with "equals" based on values of fields except when putting the instance in a Set[PersonID])
Another mystery is why I get infinite loops when I use super.hashCode() in my custom hashCode ?
PS: I use a pre initialized abstract member because I need it in my real use case...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
除了装箱数字之外,## 的整个实现就是调用 hashCode。
在 hashCode 的实现中,您正在调用(或尝试调用)##。
谜团解开了!
Outside of boxed numerics, the entire implementation of ## is to call hashCode.
In your implementation of hashCode, you are calling (or trying to call) ##.
Mystery solved!
我得到的是这样的:
发生这种情况是因为
Name
是初始化中的最后一个特征,所以它的覆盖hashCode
和equals
将是第一个称为。您希望Set
调用基于静态类型(即已声明的类型)的方法,这不是 OO 的工作方式。如果这是真的,那么继承和覆盖就几乎毫无用处。至于如何实现你想要的……你做不到。如果有一个采用
Equal[A]
类型类的Set
那就太好了,但是没有。也许斯卡拉兹有它。顺便说一句,对
super.##
的调用在 Scala 2.9.0.rc2 上被视为非法。我还不确定这意味着什么。I get this instead:
This happens because
Name
is the last trait in the initialization, so it's overrides ofhashCode
andequals
will be the first to be called. You wantedSet
to call methods based on the static type (ie, what has been declared), which is just not how OO works. If that were true, inheritance and overriding would be all but useless.As for how to accomplish what you want... you can't. It would be nice if there was a
Set
which took anEqual[A]
type class, but there isn't. Maybe Scalaz has it.By the way, there's a call to
super.##
which is deemed illegal on Scala 2.9.0.rc2. I'm not sure what that means yet.