我的应用可以比较同一抽象父类的任何两个子类的实例。我希望他们比较如下:
这些类将通过TreeMap进行比较,因此我可以选择使用Comparator,还是实现Comparable(或两者兼而有之?)。
我可以想到几种方法来做到这一点,但它们都有点混乱且容易出错。有优雅的解决方案吗?
提前致谢...
答案 0 :(得分:2)
你可以尝试
// 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
}
与其他派生类类似
答案 1 :(得分:0)
这不是你问题的直接答案,但是:
我相信你所做的是容易出错和有问题的
compareTo
方法强加的等式测试通常应返回与equals
方法相同的结果。即compareTo
方法强加的排序应与equals
一致。
如果违反此合同,您可能会遇到排序集合(您正在使用)的问题
我为什么这么说:
在某些情况下,您希望将比较委托给父类的事实向我表明您已在子类中添加了值组件。
如果你这样做,那么就无法保留equals
合同,你可能会遇到排序容器的问题(见上文)
答案 2 :(得分:0)
无论哪种方式都会出错。您可以在子类中执行以下操作:
class Subclass1 ... {
public boolean equals(Object o) {
if(o instanceof Subclass1) {
return super.equals(o);
}
... compare subclasses
}
}
答案 3 :(得分:0)
班级层次结构是否应该可扩展? =>如果它不可扩展(或很少会被扩展),您可以实现一个Comperator,以便所有比较代码都在一个地方。
订购物品的方法有多种? =>如果是这样,那么你将不得不为每个订单使用一个comperator。
从三种情况调用 compareTo(other)
(或compare(o1, o2)
):
this instanceof other.class
(即o1 instanceof o2.class
):
this
和o2
,因为它比other.class有更多的信息; other instanceof this.class
(即o2 instanceof o1.class
):
other
和this
,而this.class.compareTo应该翻转结果并将其返回。this instanceof P
&& other instanceof P
:
this
和other
:递归调用super.compareTo(other)并返回结果。答案 4 :(得分:0)
这就是我现在正在做的事情。我认为这样会很优雅:
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);
}
}
然后我只是将MyComparator
的实例传递给TreeMap
。它处理不同的子类比较,或者如果它们是相同的,则将比较传递给子类。
我不喜欢的是SubClass1.compareTo()
如果ClassCastException
是另一个子类的实例,则会抛出another
。但是,只要我确保仅通过MyComparator
比较子类,我就不必担心这一点。