在运行时覆盖现有对象的方法的任何简单方法

时间:2014-03-11 18:59:47

标签: java object runtime override

我们说我有一个域对象,这是伪代码

public class SampleClass {
  id
  title
  ... a lot of other fields from database
  public boolean equals(AnotherObj) {
       return this.id.equals(AnotherObj.id);
  }
}

equals方法基于id,适用于大多数场景。但在一种情况下,如果标题相同,则两个对象应被视为相等。 对象放在列表中,list.contains(obj)和list.indexOf(obj)被大量调用业务逻辑,这取决于equals方法。

如何在运行时覆盖equals方法? sampleClass对象可能包含复杂的树子,我不想将其复制到内存中。

我想为现有对象创建一个包装器。包装器只包含特定的equals方法,所有其他方法调用仍应传递给现有对象。

我查看了cglib,但它必须自己生成目标对象,它不能包装现有对象。

任何简单的方法?

2 个答案:

答案 0 :(得分:1)

假设您实际上在讨论Object .equals() / .hashCode(),这不是您的代码目前所做的,您可以使用Guava' s Equivalence

创建等价:

public final class SampleClassIdEquivalence
    extends Equivalence<SampleClass>
{
    // override .doEquivalent(), .doHash()
}

然后你可以像这样使用它:

final Equivalence<SampleClass> byId = new SampleClassIdEquivalence();

byId.equivalent(o1, o2);

Set<Equivalence.Wrapper<SampleClass>> set = ...

set.add(byId.wrap(whatever));

然后你可以通过名称或其他方式为等式创建其他等价物;你的选择。

事实上,Equivalence几乎与.equals() / .hashCode() ComparatorComparable的内容相同。

答案 1 :(得分:1)

我不是试图包装这些对象,而是修改类,以便它理解它应该在equals方法中检查的内容(在每个场景中)。然后在这种特殊情况下,只需设置告诉对象equals应该如何工作的任何状态成员(或其他任何东西)。请务必不要违反合同。

我还建议实际覆盖Object#equals(例如,确保您的equals接受Object,而不只是AnotherObj。 (当然,和往常一样,hashCode也是如此。)

但是如果你想要这样做,而你想用equals来做,那听起来就像the Facade pattern的工作那么Java中的痛苦:你必须创建另一个在构造函数中接受对象作为参数的整个类,通过在对象上调用它们来实现除equals之外的所有方法,然后(当然)实现{{1不同的。

基本上是这样的:

equals