4

ジェネリックについての知識が限られていることをあらかじめお詫び申し上げます

次のような状況があります。

クラス 1:

public class PostProcess implements Serializable {
    public int          order;
    // Several other variables.

    // Constructor setting vars
    public PostProcess(){

    }

    /* Getters and setters for variables */
}

クラス 2:

public class Application extends PostProcess{
    public int      subOrder;
    // Several other variables.

    // Constructor setting vars
    public Application(){

    }

    /* Getters and setters for variables */

}

クラス 3:

public class FileOperation extends PostProcess{
    public int      subOrder;
    // Several other variables (different from class 'Application').

    // Constructor setting vars
    public FileOperation(){

    }

    /* Getters and setters for variables */

}

別のクラスで達成しようとしているのは、次のように定義された「FileOperation」オブジェクトと「Application」オブジェクトの混合を含むリストをソートすることです。

private ArrayList<? extends PostProcess> processList = new ArrayList<PostProcess>();

この並べ替えは、これら両方のオブジェクトの 2 つのフィールド、つまり「order」と「subOrder」で行う必要があります。「order」は PostProcess から継承され、「subOrder」は「Application」クラスと「FileOperation」クラスの両方で定義されています。

Generics、Comparable、Comparators、Interfaces を読んでいるうちに、物事が混乱したと思います。

私は次を使用して並べ替えを適用しようとしています:

Collections.sort(processList, new PostProcessComparator());

PostProcessComparator は次のように定義されます。

public class PostProcessComparator implements Comparator<? extends PostProcess> {

    @Override
    public int compare(Object p1, Object p2) {

      int mainOrderCompare = p1.getOrder().compareTo(p2.getOrder());
      if (mainOrderCompare != 0) {
        return mainOrderCompare;
      } else {
        return p1.getSubOrder().compareTo(p2.getSubOrder());
      }
    }
}

質問:

Comparator (およびおそらくそれ以上) が間違っていることはわかっていますが、具体的な場所はわかりません。私は学ぶためにここにいます;)

  1. 「processList」リストを定義するのは正しい方法ではないことに気付きました。「FileOperation」または「Application」オブジェクトを List に追加しようとすると、コンパイラは「add(Application) に適したメソッドが見つかりません」(FileOperation の場合も同様) というメッセージで私を平手打ちします。ジェネリックを使用して processList 型を宣言できると誤って想定しましたか? 両方のクラスが PostProcess をスーパークラスとして持っているため、正しいはずですか?
  2. PostProcessComparator をクラス境界で定義することは、PostProcess をスーパークラスとして持つ (したがって同じメソッドにアクセスできる) オブジェクトのみを比較できるようにしたいので、私の目にはうまくいくはずです。
  3. p1 と p2 の Comparator クラスの引数付きオブジェクトにアクセスするにはどうすればよいですか (引数の型を宣言する必要があるためです。

    @Override
    public int compare(<What to put here?> p1, <And here?> p2) {
    
    }
    

皆さんが助けてくれることを本当に願っています!私が何か不明だった場合は、私に知らせてください。

ありがとう!

編集

NickJ と Winzu のおかげで、コンパレータと ArrayList の定義に必要な変更を加えました。

  • subOrder を Application と FileOperation から親クラスに移動しました (そしてそれらを保護しました)
  • コンパレーターのパラメーター化を次のように再定義しました。

    public class PostProcessComparator<T extends PostProcess> implements Comparator<T> 
    
  • 最初のコンパレータ比較に Integer.compare(p1.getOrder(), p2.getOrder()) を使用しました。

最後の課題 (コンパイラの警告) 呼び出し時:

    Collections.sort(processList, new PostProcessComparator());

警告が表示されます: - [unchecked] unchecked method invocation: method sort in class Collections is applied to given types

    required:  List<T>,Comparator<? super T>
    found: ArrayList<PostProcess>,PostProcessComparator

オブジェクトタイプをチェックしていないという事実を除けば、私の目にはこのコンパレーターのパラメーター化は正しいです。

これはどこが間違っていますか?

4

3 に答える 3

4

私が見つけた唯一の問題は、次のように PostProcessComparator をパラメーター化する必要があることでした。

public class PostProcessComparator<T extends PostProcess> implements Comparator<T> {

  @Override
  public int compare(T p1, T p2) {

    int mainOrderCompare = p1.getOrder().compareTo(p2.getOrder());
    if (mainOrderCompare != 0) {
      return mainOrderCompare;
    } else {
      return p1.getSubOrder().compareTo(p2.getSubOrder());
    }
  }
}

これで、compare() メソッドは正しいクラスを受け入れるようになり (PostProcess を拡張)、comlpare() 内から PostProcess のパブリック メソッドを呼び出すことができます。

最後に、フィールドは公開しないでください。フィールドを保護することをお勧めします。これにより、サブクラスは引き続きフィールドを継承できますが、カプセル化は維持されます。

于 2013-10-16T09:22:31.973 に答える
2

上記の NickJ の回答は、コンパレータの実装方法を示しています。

あなたがしていることのために、あなたも変えたいと思っています

private ArrayList<? extends PostProcess> processList = new ArrayList<PostProcess>();.

ArrayList<PostProcess> processList = new ArrayList<PostProcess>();

これが、Application et FileOperation オブジェクトをリストに追加できない理由です。

少しトリッキーです。たぶん、この投稿はあなたが理解するのを助けることができます

リストとインターフェースでジェネリックを使用する Java

親クラスにも SubOrder が必要です。

import java.io.Serializable;

public class PostProcess implements Serializable {
private int          order;
private int      subOrder;
// Several other variables.

public int getSubOrder() {
    return subOrder;
}

public void setSubOrder(int subOrder) {
    this.subOrder = subOrder;
}

public int getOrder() {
    return order;
}

public void setOrder(int order) {
    this.order = order;
}

// Constructor setting vars
public PostProcess(){

}

}

最後に、チェックされていない警告を回避するために、次のようにコンパレータを呼び出します。

 Collections.sort(processList, new PostProcessComparator<PostProcess>());
于 2013-10-16T09:46:18.630 に答える
0

次のように変更するだけです。

public class PostProcessComparator implements Comparator<PostProcess> {
    @Override
    public int compare(PostProcess p1, PostProcess p2) {
      //...
    }
}

それでおしまい。の任意の 2 つのインスタンスを比較できるコンパレータがPostProcessあります (および のサブクラスのPostProcessインスタンスは のインスタンスですPostProcess)。

于 2013-10-17T03:30:13.103 に答える