2

私のアプリは、同じ抽象親クラスの任意の2つのサブクラスのインスタンスを比較する場合があります。私はそれらを次のように比較してほしい:

  1. それらが異なるサブクラスである場合、親クラスが比較を行う必要があります。
  2. それらが同じサブクラスである場合、サブクラスが比較を行う必要があります。

クラスはTreeMapによって比較されるので、Comparatorを使用するか、Comparableを実装するか(または両方?)を選択できます。

これを行うにはいくつかの方法が考えられますが、それらはすべて少し厄介でエラーが発生しやすいものです。エレガントな解決策はありますか?

前もって感謝します...

4

5 に答える 5

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
}

他の派生クラスについても同様

于 2012-05-23T17:47:53.947 に答える
0

これはあなたの質問に対する直接的な回答ではありませんが、
あなたがしていることはエラーが発生しやすく、問題があると思います。
メソッドによって課された等価性テストは、compareTo通常、メソッドと同じ結果を返す必要がありequalsます。compareToつまり、メソッドによって課される順序は、と一致する必要equalsがあります。
この契約に違反すると、(使用している) 並べ替えられたコレクションで問題が発生する可能性があります。
なぜそう言っているのか:
特定のケースで比較を親クラスに委譲したいという事実は、サブクラスに値コンポーネントを追加したことを示しています。
これを行った場合、ファイルを保存する方法はありません。equalsコントラクトであり、ソートされたコンテナーで問題が発生する可能性があります (上記を参照)

于 2012-05-23T17:48:46.470 に答える
0

いずれにせよ、エラーが発生しやすくなります。サブクラスで次のようなことができます。

クラス サブクラス1 ... {

public boolean equals(Object o) {
  if(o instanceof Subclass1) {
    return super.equals(o);
  }

  ... compare subclasses
}

}

于 2012-05-23T17:49:57.763 に答える
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()にスローされることです。ただし、サブクラスが によってのみ比較されることを確認する限り、これについて心配する必要はありません。ClassCastExceptionanotherMyComparator

于 2012-05-23T18:33:00.333 に答える
0

クラス階層を拡張可能にする必要がありますか?
=> 拡張可能でない (またはめったに拡張されない) 場合は、Comperator を実装して、すべての比較コードを 1 か所にまとめることができます。

オブジェクトを並べ替える方法は複数ありますか? =>そうであれば、各注文に演算子を使用する必要があります。

compareTo(other)(またはcompare(o1, o2)) は、次の 3 つの状況から呼び出されます。

  1. this instanceof other.class(つまりo1 instanceof o2.class):
    • this.class は比較する必要がthisありo2、other.class よりも多くの情報を持っているためです。
  2. other instanceof this.class(つまりo2 instanceof o1.class):
    • other.class は比較otherthis、 this.class.compareTo は結果を反転して返す必要があります。
  3. this instanceof P&&となる最初の共通祖先 P が存在するother instanceof P:
    • P は比較thisして、othersuper.compareTo(other) を再帰的に呼び出し、結果を返す必要があります。
于 2012-05-23T17:57:53.310 に答える