我们说我有一个域对象,这是伪代码
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,但它必须自己生成目标对象,它不能包装现有对象。
任何简单的方法?
答案 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()
Comparator
到Comparable
的内容相同。
答案 1 :(得分:1)
我不是试图包装这些对象,而是修改类,以便它理解它应该在equals
方法中检查的内容(在每个场景中)。然后在这种特殊情况下,只需设置告诉对象equals
应该如何工作的任何状态成员(或其他任何东西)。请务必不要违反合同。
我还建议实际覆盖Object#equals
(例如,确保您的equals
接受Object
,而不只是AnotherObj
。 (当然,和往常一样,hashCode
也是如此。)
但是如果你做想要这样做,而你想用equals
来做,那听起来就像the Facade pattern的工作那么Java中的痛苦:你必须创建另一个在构造函数中接受对象作为参数的整个类,通过在对象上调用它们来实现除equals
之外的所有方法,然后(当然)实现{{1不同的。
基本上是这样的:
equals