Общие правила наследования и переопределения методов Java - PullRequest
28 голосов
/ 18 марта 2011

У меня есть абстрактный класс, который имеет универсальный метод, и я хочу переопределить универсальный метод, заменив определенные типы для универсального параметра. Итак, в псевдокоде у меня есть следующее:

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, потому что IDE eclipse постоянно напоминает мне о реализации getAndParse.

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

Ответы [ 6 ]

28 голосов
/ 18 марта 2011

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

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

10 голосов
/ 18 марта 2011

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

1 голос
/ 18 марта 2011

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

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

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

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

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

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

T x = whatever;
object.getAndParse(x); // Calls (1) even if T is derived from SpecificClass
1 голос
/ 18 марта 2011

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

1 голос
/ 18 марта 2011

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

0 голосов
/ 25 октября 2018

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

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..");
}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...