多重继承,集合和hashCode / equals覆盖

时间:2011-05-02 22:49:27

标签: scala collections multiple-inheritance

以下代码生成:
名称的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
  }
}

由于“人民”是一组PersonID,我期待以下输出:
PersonID的hashCode
PersonID的hashCode
ID = 0
ID = 1

有人可以解释这种行为以及如何做我期望的事情(也就是说,根据字段的值使用“等于”的类,除非将实例放入Set [PersonID]中)

另一个谜团是我在自定义hashCode中使用super.hashCode()时获得无限循环的原因?

PS:我使用预先初始化的抽象成员,因为我在实际用例中需要它...

2 个答案:

答案 0 :(得分:1)

我得到了这个:

Name's hashCode
Name's hashCode
Name's equals
ID=0

这是因为Name是初始化中的最后一个特征,因此hashCodeequals的覆盖将是第一个被调用的。您希望Set基于静态类型(即已声明的内容)调用方法,这不是OO的工作方式。如果这是真的,继承和压倒将是无用的。

至于如何完成你想要的......你不能。如果Set采用了Equal[A]类型类,那就太好了,但是没有。{也许Scalaz有它。

顺便说一句,调用super.##在Scala 2.9.0.rc2上被视为非法。我不确定那意味着什么。

答案 1 :(得分:1)

  

另一个谜团是我在自定义hashCode中使用super.hashCode()时获得无限循环的原因?

除了盒装数字之外,##的整个实现都是调用hashCode。

在hashCode的实现中,您正在调用(或尝试调用)##。

神秘解决了!