Javaジェネリックメソッド継承およびオーバーライドルール
-
27-10-2019 - |
質問
一般的な方法を備えた抽象クラスがあり、一般的なパラメーターの特定のタイプを置き換えることにより、一般的な方法をオーバーライドしたいと思います。したがって、擬似コードでは、次のことがあります。
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
これは、具体的にはaを持っていることを意味します getAndParse
使用できる方法。電話するとき getAndParse
その場合、コンパイラは私がの特定のインスタンスを使用したかどうかを確認するためにチェックします T
適切な方法では、特に T
拡張する必要があります AnotherClass
そしてそれはそうあるべきです SpecificClass
.
解決
ここで持っているのは、それぞれ個々のタイプパラメーターを使用した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
メソッドは、親クラスのメソッドを実装します。
他のヒント
Java Genericsの「Erasure」と呼ばれる概念のために、あなたはこの問題を見ています。 Javaは「Erasure」を使用して、後方互換性をサポートします。 IEジェネリックを使用しなかったJavaコード。
消去手順:
コンパイラは最初にタイプチェックを行い、次にすべてのタイプパラメーターを可能な限り削除(消去)(消去)、必要に応じてタイプキャストを挿入します。
例:
public abstract <T extends AnotherClass> void getAndParse(T paramAnotherClass);
となります
public abstract void getAndParse(AnotherClass paramAnotherClass);
クラス「実装者」で、
コード
public <SpecificClass> void getAndParse(T paramAnotherClass)
となります
public void getAndParse(SpecificClass paramAnotherClass){ }
コンパイラは、抽象メソッドを正しく実装していないことがわかります。抽象メソッドと実装された方法の間にはタイプの不一致があります。これがあなたがエラーを見ている理由です。
詳細については、こちらをご覧ください。http://today.java.net/pub/a/today/2003/12/02/explorations.html
いいえ、それは無効です。誰かが GetAndParse
リファレンスはそれをで呼びました 違った 拡張クラス AnotherClass
?
それは、誰かがタイプのgetandparseへの参照を持ち、getandparseメソッドを呼び出そうとするときにナンセンスになります。猫と犬が別のクラスを伸ばす場合。猫または犬と一緒にgetandparse#getandparseに電話できることを期待する必要があります。しかし、実装により、それを制限し、互換性を低下させようとしました!
それはいけません オーバーライド 特定のタイプtに、実際には(必要に応じてバイトコードレベルで)1つの方法のみがあるため 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
静的メソッドはオーバーライドできません
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..");
}}