web-dev-qa-db-ja.com

Java名前が衝突し、同じ消去があり、どちらも他方を非表示にしません

この名前の衝突エラーが発生しましたが、問題を解決する方法がわかりません。 2つのクラスがあり、オーバーロードされたメソッド「createSensors」を使用しています。ここで簡単にするために、問題を生成するコードを示します。

public abstract class ClassA {
    public static List<Sensor> createSensors(Collection<? extends ClassA> list) {
        List<Sensor> sensors = new ArrayList<Sensor>();
        for (ClassA s : list) {
           sensors.add(s.getSensor());
        }
        return sensors;
    }
}

public abstract class ClassB extends ClassA {
    public static List<Sensor> createSensors(Collection<? extends ClassB> list) {
        List<Sensor> sensors = new ArrayList<Sensor>();
        for (ClassB s : list) {
           sensors.add(s.getSensor());
        }
        return sensors;
   }
}
18
user506246

一般的な解決策は、異なる名前を使用することです。これらのメソッドはインスタンスメソッドではないため、継承関係のないクラスに含まれる可能性があります。

指摘したように、質問のメソッドの実装は同じです(タイプミスを除く)。

(オーバーロードに関するこの問題は、ランタイムタイプの消去と混同されることがよくあります。オーバーロードは動的な問題ではなくリンク時間であるため、言語で簡単に修正できます。これは特に有用な変更ではなく、推奨するのは良い考えではありません。オーバーロード。)

一般的な答え:

ここでの同じ実装の問題は別として、問題の核心は、やや野蛮な「方法Aと方法Bは同じ消去を持っている」ということです。

複雑な質問になるのは、私たちが一般的に「型消去」についてあまり知らないということです(少なくとも今朝は知りませんでした)。

短くするには:

パラメトリック型は、コンパイル時に型チェックを実行しますが(型の正確性を確認するため)、実行時に型パラメーターを忘れます(基になるメソッドの生成を回避するため)。

これは同時にシンプルで不可解に聞こえます。それを理解する最良の方法は、次の文献を参照することです。

  1. 再利用可能なタイプとは何ですか?
  2. 消去はどのような条件でどのように実行されますか?
  3. それが私のコーディング生活に何を意味するかについてのアイデア/例はありますか?
  4. それは奇妙で、私はそれが本当に好きではありませんが、なぜ彼らがそれをしたのか興味があります...

それが私を助けたのと同じくらいあなたを助けることを願っています。

具体的な答え:

あなたの場合

_public abstract class ClassA {
    public static List<Sensor> createSensors(Collection<? extends ClassA> list) {
        //do stuff
    }
}

public abstract class ClassB extends ClassA {
    public static List<Sensor> createSensors(Collection<? extends ClassB> list) {
        //do other stuff
   }
}
_

javacによって「変換」されます

_public abstract class ClassA {
    public static List createSensors(Collection list) {
        //do stuff
    }
}

public abstract class ClassB extends ClassA {
    public static List createSensors(Collection list) {
        //do other stuff
   }
}
_

一方が他方をオーバーライドできないことは明らかですが(同じタイプのパラメーターではありません)、実行時にまったく同じになります(プログラムがどちらを使用するかを選択する方法がありません)。

この問題は十分ですが、どのように解決しますか?次のいずれかの方法で続行できます。

  • 異なる名前を使用してください:createASensorscreateBSensorsこのアプローチは最も明白ですが、少しエレガントではないように見えます。

  • パラメータを追加します:createSensors(Collection<? extends ClassA> list, ClassA typeDefiner)このアプローチは野蛮に見えるかもしれませんが、少しエレガントではありませんが、メソッド<T> T[] toArray(T[] a)の_Java.util.List_で使用されるものです。

13
Ar3s