webentwicklung-frage-antwort-db.com.de

Generische Java-Methodenübernahme- und Überschreibungsregeln

Ich habe eine abstrakte Klasse, die eine generische Methode hat, und ich möchte die generische Methode überschreiben, indem der generische Parameter durch bestimmte Typen ersetzt wird. Also im Pseudocode habe ich folgendes:

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

Aber aus irgendeinem Grund darf ich das nicht? Mache ich einen Syntaxfehler oder ist diese Art der Vererbung und Überschreibung nicht zulässig? Im Besonderen erhalte ich eine Fehlermeldung über @Override, da der Eclipse IDE mich immer wieder daran erinnert, getAndParse zu implementieren.

Ich möchte, dass der obige Code funktioniert. An anderer Stelle in meinem Code gibt es eine Methode, die Instanzen von Objekten erwartet, die GetAndParse implementieren. Dies bedeutet insbesondere, dass sie eine getAndParse-Methode haben, die ich verwenden kann. Wenn ich in dieser Instanz getAndParse aufrufen, prüft der Compiler, ob ich bestimmte Instanzen von T ordnungsgemäß verwendet habe. Daher sollte TAnotherClass erweitern und SpecificClass sein.

28
davidk01

Wir haben hier zwei verschiedene Methoden mit jeweils individuellen Typparametern.

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

Dies ist eine Methode mit einem Typparameter namens T, der durch AnotherClass begrenzt ist. Dies bedeutet, dass jeder Untertyp von AnotherClass als Typparameter zulässig ist.

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

Dies ist eine Methode mit einem Typparameter namens SpecificClass, der durch Object begrenzt ist (dh jeder Typ ist als Typparameter zulässig). Willst du das wirklich?

Wird der Typparameter in Args verwendet? Ich denke, das Problem wäre da.


Die Bedeutung von 

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

ist, dass der caller der Methode entscheiden kann, mit welchem ​​Typparameter er die Methode aufrufen möchte, sofern es sich um einen Subtyp von AnotherClass handelt. Das bedeutet, dass die Methode mit beliebigen Objekten vom Typ AnotherClass aufgerufen werden kann.

Da der Aufrufer den Typparameter bestimmen kann, können Sie den Parametertyp in einer Unterklasse nicht auf SpecificClass eingrenzen. Dies wäre keine Implementierung der Methode, sondern eine andere Methode mit demselben Namen (Überladung).

Vielleicht willst du so etwas:

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

Jetzt implementiert die getAndParse-Methode die Methode der übergeordneten Klasse.

28
Paŭlo Ebermann

Sie sehen dieses Problem aufgrund des Konzepts "Erasure" in Java Generics . Java verwendet "Erasure", um die Abwärtskompatibilität zu unterstützen. Java-Code, der keine Generics verwendet.

Löschverfahren:
Der Compiler führt zuerst eine Typprüfung durch und entfernt (löscht) dann alle Typparameter so weit wie möglich und fügt bei Bedarf auch TypeCasting ein.

beispiel:

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

wird werden

public abstract void getAndParse(AnotherClass paramAnotherClass);

In der Klasse "Implementor.Java" 

Der Code

public <SpecificClass> void getAndParse(T paramAnotherClass)

wird werden

public void getAndParse(SpecificClass paramAnotherClass){  }

der Compiler wird feststellen, dass Sie die abstrakte Methode nicht korrekt implementiert haben .. Es besteht ein Typkonflikt zwischen der abstrakten Methode und der implementierten Methode. Deshalb sehen Sie den Fehler.

Weitere Details finden Sie hier . http://today.Java.net/pub/a/today/2003/12/02/explorations.html

10
kensen john

Nein, das ist nicht gültig. Was würde passieren, wenn jemand mit einer GetAndParse-Referenz mit einer anderen class-Erweiterung AnotherClass aufruft? 

1
Erik

Dies wird zu einem Blödsinn, wenn jemand eine Referenz auf den Typ GetAndParse hat und versucht, die getAndParse-Methode aufzurufen. Wenn Katze und Hund eine AnotherClass verlängern. Ich sollte erwarten, GetAndParse # getAndParse entweder mit einer Katze oder einem Hund aufrufen zu können. Die Implementierung hat jedoch versucht, sie einzuschränken und weniger kompatibel zu machen!

1
Affe

Sie können override nicht auf einen bestimmten Typ T anwenden, da es tatsächlich (auf Bytecode-Ebene, wenn Sie möchten) nur eine Methode getAndParse gibt, weil der Typ gelöscht wurde (siehe andere Antwort):

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

Für jede Art von T wird dieselbe Methode verwendet.

Sie können Überladung it (ich denke):

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

dies ist jedoch keine andere Methode als (1) und es wird nicht durch generischen Code aufgerufen:

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

Statische Methode kann nicht überschreiben

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

Private Methode kann nicht überschreiben

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

Endgültige Methode kann nicht überschrieben werden

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