multiple inherance, Sets and hashCode/equals overriding
The code below generates:
Name's hashCode Name's hashCode Name's equals ID=0import 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=1Does 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...
I get this instead:
Name's hashCode
Name's hashCode
Name's equals
ID=0
This happens because Name
is the last trait in the initialization, so it's overrides of hashCode
and equals
will be the first to be called. You wanted Set
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 an Equal[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.
Another mystery is why I get infinite loops when I use super.hashCode() in my custom 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!
精彩评论