【问题标题】:Dynamically override `equals` and `hashCode` in groovy在groovy中动态覆盖`equals`和`hashCode`
【发布时间】:2013-06-20 09:49:19
【问题描述】:

如果我为一个类动态覆盖equalshashCode 方法,调用这些方法直接调用被覆盖的版本,但将它们用于set 使用非覆盖版本。为什么会这样?是否仍然可以为所有用途动态覆盖这两种方法?

class SuperClass {
  public boolean equals(Object other) {
    println 'non overridden equals called'
    false
  }

  public int hashCode() {
    println 'non overridden hashCode called'
    1
  }
}

SuperClass.metaClass.equals = { Object other ->
  println 'overridden equals called'
  true
}

SuperClass.metaClass.hashCode = { ->
  println 'overridden hashCode called'
  1
}

def a = new SuperClass()
def b = new SuperClass()

println a.hashCode() // overriden hashCode called
println b.hashCode() // overriden hashCode called
println a.equals(b) // overriden equals called

println([a, b].toSet().size()) // non overriden methods called, returns 2 instead of 1

【问题讨论】:

  • 你在哪里覆盖了元类中Set的equals()和hashcode()?
  • 为什么我需要覆盖Setequalshashcode
  • 抱歉,问题看了一半:-)

标签: groovy overriding equals hashcode


【解决方案1】:

List invokes the following code 上调用toSet()

    Set<T> answer = new HashSet<T>(self.size());
    answer.addAll(self);
    return answer;

现在HashSet(Java 类)没有metaClass 的概念,因此看不到您重载的hashCodeequals 方法。因此,您的套装中有 2 件物品。

你可以做的是首先在你的名单上打电话unique

println( [a, b].unique().toSet().size() ) 

因为这通过调用者所以知道metaClass 并且应该给你一个包含一个元素的集合。

实际上,我会避免通过元类更改hashCode 方法。如您所见,很难确切知道它何时会被处理,而且处理得好的事情可能不会期望 hashCode 时时发生变化。

【讨论】:

  • 那么使用 groovy 没有办法覆盖方法,所以 Java 类会看到更改?
  • Java 类不知道metaClass,所以是的,Java 代码不会看到更改(除非它通过使用 Groovy 调用程序或检查元类本身来查找它)
  • 在动态覆盖 toString() 方法时也有类似的问题。 jira.codehaus.org/browse/GROOVY-2599
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-24
  • 2020-06-09
  • 1970-01-01
  • 2011-07-08
  • 2017-11-19
  • 1970-01-01
相关资源
最近更新 更多