比较Java子类
我的应用程序可以比较同一抽象父类的任意两个子类的实例。我希望将它们进行如下比较:比较Java子类,java,Java,我的应用程序可以比较同一抽象父类的任意两个子类的实例。我希望将它们进行如下比较: 如果它们是不同的子类,则父类应进行比较 如果它们是相同的子类,则子类应进行比较 这些类将通过树映射进行比较,因此我可以选择使用比较器,或者实现Comparable(或者两者兼而有之) 我可以想出几种方法来做到这一点,但它们都有点混乱和容易出错。有优雅的解决方案吗 提前谢谢…您可以试试 // Parent: @Override public final int compareTo(Parent other) {
// Parent:
@Override
public final int compareTo(Parent other)
{
if (getClass() == other.getClasss()) {
// same type -> pass it to subclass implementation
return this.subCompare(other)
}
// different type -> do the comparison here based on Parent's logic
// ...
}
protected int subCompare(Parent other)
{
// this should not be called directly
return 0; // could throw an exception here too
}
// Derived1:
@Override
protected int subCompare(Parent other)
{
// this method is only called from Parent
Derived1 other1 = (Derived1) other;
// do the comparison based on Derived1's logic
}
类似地,对于其他派生类这不是对您问题的直接回答,而是:
我相信你所做的事情容易出错,而且有问题。
compareTo
方法施加的相等性测试通常应返回与equals
方法相同的结果。也就是说,compareTo
方法施加的顺序应与equals
一致如果违反此约定,您可能会遇到排序集合(您正在使用的)问题。
我为什么这么说:
在某些情况下,您希望将比较委托给父类,这一事实向我表明,您已在子类中添加了一个值组件。
如果您这样做了,那么就不可能保留
equals
契约,并且您可能会遇到排序容器的问题(请参见上文)无论哪种方式都很容易出错。您可以在子类中执行以下操作:
类子类1。。。{
public boolean equals(Object o) {
if(o instanceof Subclass1) {
return super.equals(o);
}
... compare subclasses
}
}类层次结构是否应可扩展?
=>如果不可扩展(或很少会扩展),您可以实现Comperator,以便所有比较代码都位于一个位置 是否有不止一种方式来排列对象? =>如果是这样,那么您必须为每个订单使用comperator
compareTo(其他)
(或compare(o1,o2)
)从以下三种情况调用:
其他.class的此实例
(即o2.class的o1实例):
- this.class应该比较
和this
,因为它比其他.class有更多的信息李>o2
此.class的其他实例
(即o1.class的o2实例
):
- other.class应比较
和other
和this.class.compare,以翻转结果并返回结果this
此P实例
和&其他P实例
:
- P应该比较
和此
:递归调用super.compareTo(其他)并返回结果其他
我现在就是这样做的。我认为这是最优雅的:
public abstract class ParentClass implements Comparable<ParentClass> {
// compareTo(ParentClass) is implicitly abstract
}
public class SubClass1 extends ParentClass /* Comparable<> is implicitly implemented */ {
@Override
public int compareTo(ParentClass another) {
SubClass1 subAnother = (SubClass1) another;
return /* result of sub-class comparison */;
}
}
public class MyComparator implements Comparator<ParentClass> {
@Override
public int compare(ParentClass lhs, ParentClass rhs) {
// Are lhs and rhs instances of the same sub-class?
if(!lhs.getClass().equals(rhs.getClass()))
// They are different. Use parent class comparison.
return /* result of parent class comparison */;
// They are the same. Use sub-class comparison.
return lhs.compareTo(rhs);
}
}
公共抽象类ParentClass实现了可比较的{
//compareTo(父类)是隐式抽象的
}
公共类子类1扩展了ParentClass/*Compariable,隐式实现了*/{
@凌驾
公共整数比较(父类另一个){
第1子类另一子类=(第1子类)另一子类;
返回/*子类比较结果*/;
}
}
公共类MyComparator实现了Comparator{
@凌驾
公共整数比较(父类lhs、父类rhs){
//lhs和rhs实例是否属于同一子类?
如果(!lhs.getClass().equals(rhs.getClass()))
//它们是不同的。请使用父类比较。
返回/*父类比较结果*/;
//它们是相同的。使用子类比较。
返回左侧比较(右侧);
}
}
然后我只需将MyComparator
的一个实例传递到TreeMap
。它处理不同的子类比较,或者将比较传递给相同的子类
我不喜欢的是,如果
另一个是另一个子类的实例,则子类1.compareTo()
将抛出ClassCastException
。但是,只要我确保子类仅由MyComparator比较,我就不必担心这一点。你所说的“类将由树映射进行比较”是什么意思?既然你提到了Comparable和Comparator,那么我们可以假设比较的结果有三种可能性—“小于”,“大于”和“等于”?如果比较排除了其中一个选项的可能性,那么您不应该使用这些接口。您的意思是通过反射来比较类吗?每个类都有哪些方法和属性?这是一项非常困难的任务,因为compare()的契约规定了传递性:如果b1>b2(与B子类比较),如果a>b1(与基类比较),那么必须有a>b2(与基类比较)。考虑到基类比较对子类比较一无所知,这是很难实现的。@JBNizet-虽然我不认为OP的想法一定很好,但我认为只要子类排序始终是“子比较”,保持传递性并不困难将可能使父级compare()成为最终的,以避免意外重写。否则,只要不需要在层次结构中的任意深度做出决策,这就行了。仅供参考。“this instanceof other.getClasss()”在Java中不是有效语句……是的,您只需要“getClass()==other.getClass()”谢谢。这是接近我已经在做的,可能是优雅的,因为它将得到。除了我使用的是Comparator和Comparable的混合解决方案:Comparator检查它们是否是不同的子类,如果是,则处理比较。否则,它将调用subclass.compareTo()。@BarryFruitman您可以通过首先根据基类规则进行比较来改进保证,并且只有当它们相等时,才打破