开发者

multiple inherance, Sets and hashCode/equals overriding

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...


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!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜