Переопределить метод с помощью общих параметров в Java? - PullRequest
41 голосов
/ 27 октября 2008

У меня есть абстрактный класс Monitor.java , который разделен на класс EmailMonitor.java .

Метод:

public abstract List<? extends MonitorAccount> performMonitor(List<? extends MonitorAccount> accounts)

определено в Monitor.java и должно быть переопределено в EmailMonitor.java .

В настоящее время у меня есть метод, переопределенный в EmailMonitor.java следующим образом:

@Override
public List<EmailAccount> performMonitor(List<EmailAccount> emailAccounts) {
    //...unrelated logic
    return emailAccounts;
}

Однако это приводит к ошибке времени компиляции:

Name clash: The method performMonitor(List<EmailAccount>) of type EmailMonitor has the same erasure as performMonitor(Lis<? extends MonitorAccount> emailAccounts) of type Monitor but does not override it

EmailAccount - это подкласс MonitorAccount, поэтому (по крайней мере, на мой взгляд) его переопределение имеет смысл. Видя, что компилятор недоволен моей логикой: как мне поступить правильно, сохраняя проверки времени компиляции, чтобы все вызовы EmailMonitor.performMonitor() получали списки EmailAccount, а не какой-то другой тип MonitorAccount?

Ответы [ 2 ]

34 голосов
/ 27 октября 2008

Нет, это не отменяет это должным образом. Переопределение означает, что вы должны быть в состоянии справиться с любым допустимым вводом в базовый класс. Подумайте, что произойдет, если клиент сделает это:

Monitor x = new EmailMonitor();
List<NonEmailAccount> nonEmailAccounts = ...;
x.performMonitor(nonEmailAccounts);

Там нет ничего, что могло бы дать ошибку во время компиляции, учитывая ваше описание - но это явно неправильно.

Мне кажется, что Monitor должно быть общим для типа учетной записи, которую он может отслеживать, поэтому ваш EmailMonitor должен расширяться Monitor<EmailAccount>. Итак:

public abtract class Monitor<T extends MonitorAccount>
{
    ...
    public abstract List<? extends T> performMonitor(
        List<? extends T> accounts);
}

public class EmailMonitor extends Monitor<EmailAccount>
{
    @Override
    public abstract List<? extends EmailAccount> performMonitor(
        List<? extends EmailAccount> accounts)
    {
        // Code goes here
    }
}

Вы, возможно, захотите тщательно подумать об обобщениях в вызове performMonitor - что означает возвращаемое значение?

9 голосов
/ 27 октября 2008

Вот мое собственное решение. Я подозреваю, что это то же самое, на что пытался добраться Джон Скит ... без опечатки (см. Мой комментарий в ответ на его ответ).

Monitor.java класс:

public abstract class Monitor <T extends MonitorAccount> {
  ...
  public abstract List<T> performMonitor(List<T> accounts);
  ..
}

EmailMonitor.java

public class EmailMonitor extends Monitor<EmailAccount> {
  ...
  public List<EmailAccount> performMonitor(List<EmailAccount> emailAccounts) {
    ..//logic...logic...logic
    return emailAccounts;
  }
  ...
}

В этой конфигурации EmailMonitor.performMonitor () всегда проверяет во время компиляции, что он получает список EmailAccount , а не любые другие мои типы FTPAccount, DBAccount , и т.д ... Это намного чище, чем альтернатива, которая бы получала / отправляла необработанный список и затем приводила к принудительному приведению к нему требуемого типа, что приводило к потенциальным исключениям приведения типов во время выполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...