【问题标题】:multiple inherance, Sets and hashCode/equals overriding多重继承、Sets 和 hashCode/equals 覆盖
【发布时间】:2011-05-02 22:49:27
【问题描述】:

下面的代码生成:
名称的 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:我使用预初始化的抽象成员,因为我在实际用例中需要它......

【问题讨论】:

    标签: scala collections multiple-inheritance


    【解决方案1】:

    我得到了这个:

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

    发生这种情况是因为 Name 是初始化中的最后一个 trait,所以它的覆盖 hashCodeequals 将是第一个被调用的。您希望Set 调用基于静态类型(即已声明的内容)的方法,但这不是面向对象的工作方式。如果这是真的,那么继承和覆盖将毫无用处。

    至于如何完成你想要的……你做不到。如果有一个 Set 采用 Equal[A] 类型类,那就太好了,但没有。也许 Scalaz 有。

    顺便说一句,在 Scala 2.9.0.rc2 上调用 super.## 是非法的。我还不确定这意味着什么。

    【讨论】:

    • 感谢您的回答,现在很明显我必须以不同的方式实现它。
    【解决方案2】:

    另一个谜团是为什么我在自定义 hashCode 中使用 super.hashCode() 时会出现无限循环?

    在盒装数字之外,## 的整个实现就是调用 hashCode。

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

    谜团解开!

    【讨论】:

    • 我认为不应该发生递归,因为我打算调用 super.hashCode(),而不是 this.hashCode()。和你一样,我在想 hashCode 和 ## 确实是同一种方法,但是在通过 hashCode() 更改 ## 后,无限循环消失了......
    • 我很确定它是如何工作的,因为我写了它。 ## 调用 hashCode。我不确定您不清楚其中的哪一部分,或者我会进一步详细说明。
    • 不清楚的是,尽管调用了 super.##,但我得到了无限循环。 scala论坛上的另一个人给了我以下解释:“您的无限循环是由在hashCode方法的定义中使用super.##引起的。调用x.##将转换为调用ScalaRunTime.hash(x) ,反过来,对于 AnyRef 的后代,将调用 x.hashCode()。在这里使用 super 对您没有帮助。如果您使用 super.hashCode(),那么您将获得您似乎期望的行为。"
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    • 2020-06-09
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多