47

ジェネリックメソッドを持つ抽象クラスがあり、ジェネリックパラメーターを特定の型に置き換えてジェネリックメソッドをオーバーライドしたいと思います。したがって、擬似コードでは、次のようになります。

public abstract class GetAndParse {
  public SomeClass var;

  public abstract <T extends AnotherClass> void getAndParse(T... args);
}

public class Implementor extends GetAndParse {
  // some field declarations

  // some method declarations

  @Override
  public <SpecificClass> void getAndParse(SpecificClass... args) {
    // method body making use of args
  }
}

しかし、何らかの理由で私はこれを行うことを許可されていませんか?ある種の構文エラーが発生していますか、それともこの種の継承とオーバーライドは許可されていませんか?@Override具体的には、Eclipse IDEが実装するように通知し続けるため、エラーが発生しますgetAndParse

上記のコードを機能させる方法は次のとおりです。私のコードのどこかに、実装するオブジェクトのインスタンスを期待するメソッドがあります。GetAndParseこれは、具体的には、getAndParse使用できるメソッドがあることを意味します。そのインスタンスを呼び出すとgetAndParse、コンパイラは、の特定のインスタンスを適切な方法で使用したかどうかを確認しますT。したがって、特にT拡張AnotherClassする必要があり、そうする必要がありますSpecificClass

4

6 に答える 6

39

ここにあるのは、それぞれ個別のタイプパラメータを持つ2つの異なるメソッドです。

public abstract <T extends AnotherClass> void getAndParse(Args... args);

これは、Tという名前の型パラメーターを持ち、で囲まれたメソッドですAnotherClass。つまり、の各サブタイプはAnotherClass型パラメーターとして許可されます。

public <SpecificClass> void getAndParse(Args... args)

SpecificClassこれは、で囲まれた、という名前の型パラメーターを持つメソッドですObject(つまり、各型は型パラメーターとして許可されます)。本当にこれが欲しいですか?

タイプパラメータは内部で使用されていArgsますか?問題はそこにあると思います。


の意味

public abstract <T extends AnotherClass> void getAndParse(T... args);

これは、メソッドの呼び出し元が、メソッドのサブタイプである限り、メソッドを呼び出すタイプパラメーターを決定できることですAnotherClass。これは、事実上、メソッドはタイプの任意のオブジェクトで呼び出すことができることを意味しますAnotherClass

呼び出し元は型パラメーターを決定できるため、サブクラスでパラメーター型を絞り込むことはできません。SpecificClassこれはメソッドの実装ではなく、同じ名前の別のメソッド(オーバーロード)になります。

多分あなたはこのようなものが欲しいでしょう:

public abstract class GetAndParse<T extends AnotherClass> {
  public SomeClass var;

  public abstract void getAndParse(T... args);
}

public class Implementor extends GetAndParse<SpecificClass> {
  // some field declarations

  // some method declarations

  @Override
  public void getAndParse(SpecificClass... args) {
    // method body making use of args
  }
}

これで、getAndParseメソッドは親クラスのメソッドを実装します。

于 2011-03-18T01:45:08.683 に答える
19

この問題は、JavaGenericsの「消去」と呼ばれる概念が原因で発生しています。Javaは、下位互換性をサポートするために「消去」を使用します。つまり、ジェネリックを使用しなかったJavaコード。

消去手順:
コンパイラーは最初に型チェックを実行し、次にすべての型パラメーターを可能な限り削除(消去)し、必要に応じてTypeCastingを挿入します。

例:

public abstract <T extends AnotherClass> void getAndParse(T paramAnotherClass);

となります

public abstract void getAndParse(AnotherClass paramAnotherClass);

クラス「Implementor.java」では、

コード

public <SpecificClass> void getAndParse(T paramAnotherClass)

となります

public void getAndParse(SpecificClass paramAnotherClass){  }

コンパイラは、抽象メソッドが正しく実装されていないことを認識します。抽象メソッドと実装メソッドの間に型の不一致があります。これが、エラーが表示される理由です。

詳細については、こちらをご覧ください。 http://today.java.net/pub/a/today/2003/12/02/explorations.html

于 2011-03-18T01:26:57.230 に答える
2

型消去のために実際には(必要に応じてバイトコードレベルで)1つのメソッドしかないため、特定の型TにオーバーライドすることはできませんgetAndParse(他の回答を参照)。

public abstract void getAndParse(AnotherClass... args); // (1)

すべてのタイプのTに対して、同じ方法が使用されます。

あなたはそれをオーバーロードすることができます(私は思う):

public void getAndParse(SpecificClass... args); // (2)

ただし、これは(1)と同じメソッドであり、汎用コードによって呼び出されることはありません。

T x = whatever;
object.getAndParse(x); // Calls (1) even if T is derived from SpecificClass
于 2011-03-18T01:54:21.447 に答える
1

いいえ、無効です。GetAndParse参照を持つ誰かが別のクラスを拡張してそれを呼び出した場合はどうなりAnotherClassますか?

于 2011-03-18T00:44:21.823 に答える
1

誰かがGetAndParseタイプへの参照を持っていて、getAndParseメソッドを呼び出そうとすると、それは意味がなくなります。猫と犬がAnotherClassを拡張する場合。猫か犬のどちらかでGetAndParse#getAndParseを呼び出すことができると期待する必要があります。しかし、実装はそれを制限し、互換性を低下させようとしました!

于 2011-03-18T00:45:12.520 に答える
0

静的メソッドはオーバーライドできません

class Vehicle{
static void park(int location){
    System.out.println("Vehicle parking..");
}}

class Car extends  Vehicle{
@Override //error
void park(int location) { //error
    System.out.println("Car Parking..");
}}

プライベートメソッドはオーバーライドできません

class Vehicle{
private void park(int location){
    System.out.println("Vehicle parking..");
}
void callPark(){
    park(100);
}}

class Car extends  Vehicle{
//@Override
void park(int location) {
    System.out.println("Car Parking..");
}}

class Demo {
public static void main(String[] args) {
    Vehicle v1=new Car();
   v1.callPark();
}}

Finalメソッドはオーバーライドできません

class Vehicle{
final void park(int location){
    System.out.println("Vehicle parking..");
}}

class Car extends  Vehicle{
//@Override
void park(int location) { //error
    System.out.println("Car Parking..");
}}
于 2018-10-25T18:30:26.280 に答える