Общие правила наследования и переопределения методов 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
  }
}

Но по какой-то причине мне не разрешено это делать? Я делаю какую-то синтаксическую ошибку или этот тип наследования и переопределения не допускается? В частности, я получаю сообщение об ошибке @Override потому что Eclipse IDE постоянно напоминает мне о реализации getAndParse,

Вот как я хочу, чтобы вышеуказанный код работал. Где-то еще в моем коде есть метод, который ожидает экземпляры объектов, которые реализуют GetAndParse что конкретно означает, что у них есть getAndParse метод, который я могу использовать. Когда я звоню getAndParse в этом случае компилятор проверяет, использовал ли я конкретные экземпляры T надлежащим образом, в частности, T должен продлить AnotherClass и это должно быть SpecificClass,

6 ответов

Решение

Здесь мы имеем два разных метода с индивидуальными параметрами типа каждый.

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 Метод реализует метод родительского класса.

Вы видите эту проблему из-за концепции под названием "Erasure" в Java Generics. 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

Вы не можете переопределить конкретный тип 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

Нет, это не действительно. Что будет, если кто-то с GetAndParse ссылка назвала это с другим расширением класса AnotherClass?

Это становится бессмысленным, когда кто-то ссылается на тип GetAndParse и пытается вызвать метод getAndParse. Если Кошка и Собака расширяют AnotherClass. Я должен ожидать, что смогу вызвать GetAndParse#getAndParse с помощью Cat или Dog. Но реализация попыталась ограничить его и сделать его менее совместимым!

Статический метод не может переопределить

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..");
}}
Другие вопросы по тегам