Pregunta

Tengo una clase abstracta que tiene un método genérico y quiero anular el método genérico sustituyendo tipos específicos por el parámetro genérico. Entonces, en pseudo-código tengo lo siguiente:

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

¿Pero por alguna razón no se me permite hacer esto? ¿Estoy cometiendo algún tipo de error de sintaxis o este tipo de herencia y primordial no está permitido? Específicamente recibo un error sobre @Override Porque el IDE de Eclipse me recuerda a implementar getAndParse.

Así es como quiero que funcione el código anterior. En otro lugar de mi código hay un método que espera instancias de objetos que implementen GetAndParse que específicamente significa que tienen un getAndParse método que puedo usar. Cuando llamo getAndParse En ese caso, el compilador verifica si he usado instancias específicas de T de la manera adecuada, así que en particular T Debería extenderse AnotherClass y debería ser SpecificClass.

¿Fue útil?

Solución

Lo que tenemos aquí son dos métodos diferentes con parámetros de tipo individual cada uno.

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

Este es un método con un parámetro de tipo llamado T, y limitado por AnotherClass, lo que significa cada subtipo de AnotherClass está permitido como un parámetro de tipo.

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

Este es un método con un parámetro de tipo nombrado SpecificClass, delimitada por Object (lo que significa que cada tipo está permitido como un parámetro de tipo). ¿De verdad quieres esto?

Es el parámetro de tipo utilizado dentro Args? Creo que el problema estaría ahí.


El significado de

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

es que el llamador del método puede decidir con qué parámetro de tipo quiere llamar al método, siempre y cuando sea un subtipo de AnotherClass. Esto significa que, en efecto, el método se puede llamar con cualquier objeto de tipo AnotherClass.

Dado que la persona que llama puede decidir el parámetro de tipo, no puede en una subclase reducir el tipo de parámetro a SpecificClass - Esto no sería una implementación del método, sino otro método con el mismo nombre (sobrecarga).

Quizás quieras algo como esto:

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

Ahora el getAndParse El método implementa el método de la clase principal.

Otros consejos

Estás viendo este problema debido al concepto llamado "borrado" en Java Generics. Java usa "borrado" para admitir la compatibilidad con atraso. es decir, código Java que no usaba genéricos.

Procedimiento de borrado:
El compilador primero hará una verificación de tipo y luego eliminará (borrará) todos los parámetros de tipo tanto como sea posible, y también insertará el typecasting cuando sea necesario.

ejemplo:

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

se convertirá

public abstract void getAndParse(AnotherClass paramAnotherClass);

En clase "implementer.java",

El código

public <SpecificClass> void getAndParse(T paramAnotherClass)

se convertirá

public void getAndParse(SpecificClass paramAnotherClass){  }

El compilador verá que no ha implementado el método abstracto correctamente. Existe un tipo de falta de coincidencia entre el método abstracto y el método implementado. Por eso está viendo el error.

Más detalles se pueden encontrar aquí.http://today.java.net/pub/a/today/2003/12/02/explorations.html

No, no es válido. ¿Qué pasaría si alguien con un GetAndParse referencia lo llamó con una diferente Extensión de la clase AnotherClass?

Eso se convierte en una tontería cuando alguien tiene una referencia al tipo GetAndParse e intenta llamar al método GetAndParse. Si el gato y el perro extienden otra clase. Debería esperar poder llamar a GetAndParse#GetAndParse con un gato o un perro. ¡Pero la implementación ha tratado de restringirlo y hacerlo menos compatible!

No puedes anular al tipo específico T porque de hecho hay (en el nivel de bytecodo si lo desea) solo un método getAndParse Debido al tipo de borrado (ver otra respuesta):

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

Para cada tipo de T, se utiliza el mismo método.

Puedes sobrecarga Es (creo):

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

pero este no será un método diferente de (1) hormiga lo hará no ser llamado por código genérico:

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

El método estático no puede anular

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

El método privado no puede anular

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

El método final no puede anular

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..");
}}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top