4

クラスが Comparable を実装する場合の compareTo() メソッドの定義のベスト プラクティスを探しています。したがって、メソッドのシグネチャは

public int compareTo(BaseClass arg)

最初にすべきことは、arg がこのクラスのインスタンスかどうかを確認することです。そうであれば、クラスにキャストし、メンバーを比較します。しかし、引数がこのクラスのものではなく、BaseClass を実装する他のクラスのものである場合、何を返せば再帰的になるでしょうか?

ベスト プラクティスは、そのクラスに対してのみ compareTo() を定義することですが、その水はダムの上にあります。

4

3 に答える 3

3

有効な Java の項目 12 からの引用:

compareTo コントラクトの規定について見ていきましょう。最初の規定は、2 つのオブジェクト参照間の比較の方向を逆にすると、期待どおりの結果が得られることを示しています。最初のオブジェクトが 2 番目のオブジェクトと等しい場合、2 番目のオブジェクトは最初のオブジェクトと等しくなければなりません。また、最初のオブジェクトが 2 番目のオブジェクトよりも大きい場合、2 番目のオブジェクトは最初のオブジェクトよりも小さくなければなりません。2 番目の規定は、1 つのオブジェクトが 2 番目よりも大きく、2 番目が 3 番目よりも大きい場合、1 番目は 3 番目よりも大きくなければならないことを示しています。最後の条項は、等しいと比較されるすべてのオブジェクトは、他のオブジェクトと比較したときに同じ結果をもたらさなければならないことを示しています。

これら 3 つの規定の結果の 1 つは、compareTo メソッドによって課される等値テストは、equals 契約によって課されるのと同じ制限 (再帰性、対称性、および推移性) に従わなければならないということです。したがって、同じ警告が適用されます。 オブジェクト指向の抽象化 (項目 8) の利点を放棄する意思がない限り、compareTo コントラクトを保持しながらインスタンス化可能なクラスを新しい値コンポーネントで拡張する方法はありません。同じ回避策も適用されます。Comparable を実装するクラスに値コンポーネントを追加する場合は、それを拡張しないでください。最初のクラスのインスタンスを含む無関係なクラスを作成します。次に、このインスタンスを返す「view」メソッドを提供します。これにより、必要に応じてそのクライアントが 2 番目のクラスのインスタンスを最初のクラスのインスタンスとして表示できるようにしながら、2 番目のクラスで好きな compareTo メソッドを自由に実装できます。

@BalusC が彼のコメントで推奨していることを実行する必要があります。すべての子クラスに対して基本クラスの compareTo() メソッドを使用するか、最初のクラスのインスタンスを含む無関係なクラスを作成して上記の回避策を実行してください。

于 2011-08-16T22:02:19.247 に答える
2

あなたの間違いはあなたの質問にあります。を実装する必要はありませんpublic int compareTo(BaseClass arg)。「public int compareTo(YourClass arg)」を実装する必要があります。

この場合instanceof、キャストを使用して実行する必要はありません。これがジェネリックが導入された理由です: キャストを避けるためです。

ただし、基本クラスを引数として使用したい場合は、少なくとも次のことを行ってください。

public class Test {

}

class SubTest <T extends Test> implements Comparable<T> {
    @Override
    public int compareTo(T o) {
        // add your code with instanceof here
        return 0;
    }
}

少なくともこのアプローチでは、引数が基本クラスのサブクラスである必要があります。

于 2011-08-16T21:47:25.283 に答える
1

この文脈では、再帰的とは を意味しobj.compareTo(obj) == 0ます。ここでの反射的とはどういう意味ですか?

compareTo(T o) の指定されたコントラクトに関する限り、必要なセマンティクスは、関連するクラスを意味のある形で比較できない場合に ClassCastException をスローすることです。

例: 与えられた

class Fruit {/* ..*/ }

class Apple extends Fruit {/* .. */ }

@Ignore("bad OO")
class GrannySmithApple extends Apple {/* .. */ }

class Orange extends Fruit {/* ... */ }

と主張することができます

   Fruit a = new Apple();
   Fruit b = new GrannyApple();
   Fruit c = new Orange();

   // compare apples with apple?
   // makes sense to expect an int value
   r = a.compareTo(b)

   // compare apples with oranges?
   // makes sense to expect an exception
   boolean excepted = false;
   try {
       c.compareTo(a);
   } catch (ClassCastException e) { 
      excepted = true;
   } finally {
      assert excepted : "How can we compare apples with oranges?"
   }
于 2011-08-16T22:05:00.000 に答える