Подтвердить что ты не робот

Стандартные методы наследования и переопределения методов 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 продолжает напоминать мне о внедрении getAndParse.

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

4b9b3361

Ответ 1

Что мы имеем здесь, это два разных метода с индивидуальными параметрами каждого.

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

Это метод с параметром типа с именем T и ограниченный AnotherClass, что означает, что каждый подтип AnotherClass разрешен как параметр типа.

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

Это метод с параметром типа с именем SpecificClass, ограниченный Object (что означает, что каждый тип разрешен как параметр типа). Вы действительно этого хотите?

Является ли параметр типа, используемым внутри Args? Я думаю, проблема будет там.


Edit:

Значение

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

Ответ 2

Вы видите эту проблему из-за концепции "Erasure" в Java Generics. Java использует "стирание" для поддержки обратной совместимости. т.е. Java-код, который не использовал дженерики.

Процедура Erasure:
Компилятор сначала проверит проверку типов, а затем удалит (стирает) все параметры типа как можно больше, а также добавит 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

Ответ 3

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

Ответ 4

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

Ответ 5

Вы не можете переопределить конкретный тип T, потому что на самом деле (на уровне байт-кода, если хотите) используется только один метод getAndParse из-за стирания типа (см. другой ответ):

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

Для каждого типа T используется тот же метод.

Вы можете перегрузить его (я думаю):

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

но это не будет отличаться от (1) ant, он не будет вызываться общим кодом:

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