web-dev-qa-db-ja.com

Java汎用メソッドの継承とオーバーライド規則

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

_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
  }
}
_

しかし、何らかの理由で私はこれを行うことはできませんか?何らかの構文エラーを起こしていますか、またはこの種の継承とオーバーライドは許可されていませんか?具体的には、Eclipse IDE=がgetAndParseを実装することを思い出させ続けるため、_@Override_に関するエラーが発生します。

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

30
davidk01

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

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

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

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

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

TypeパラメーターはArgs内で使用されていますか?問題があると思います。


の意味

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

メソッドのcallerは、これが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メソッドは親クラスのメソッドを実装します。

30
Paŭlo Ebermann

Java Genericsの「Erasure」という概念のため、この問題が発生しています。 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

11
kensen john

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

1
Erik

誰かがGetAndParse型への参照を持ち、getAndParseメソッドを呼び出そうとすると、それはナンセンスになります。 CatとDogがAnotherClassを拡張する場合。 CatまたはDogのいずれかを使用してGetAndParse#getAndParseを呼び出すことができるはずです。しかし、実装はそれを制限し、互換性を低くしようとしました!

1
Affe

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

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

Tのタイプごとに、同じ方法が使用されます。

オーバーロード it(私は思う):

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

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

T x = whatever;
object.getAndParse(x); // Calls (1) even if T is derived from SpecificClass
1
ysdx

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

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();
}}

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

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..");
}}
0
Ishan Lakshitha