多重继承、集合和 hashCode/equals 重写

发布于 2024-11-04 07:41:59 字数 1987 浏览 0 评论 0原文

下面的代码生成:
名称的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

橘和柠 2024-11-11 07:42:00

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

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

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

谜团解开了!

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!

烟─花易冷 2024-11-11 07:41:59

我得到的是这样的:

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

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

至于如何实现你想要的……你做不到。如果有一个采用 Equal[A] 类型类的 Set 那就太好了,但是没有。也许斯卡拉兹有它。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文