44

我有一个抽象类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

4

2 回答 2

36

不,它没有正确地覆盖它。覆盖意味着您应该能够处理对基类的任何有效输入。考虑如果客户这样做会发生什么:

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调用中的泛型 - 返回值意味着什么?

于 2008-10-27T11:56:23.500 回答
10

这是我自己的解决方案。我怀疑这与 Jon Skeet 试图达到的目的是一样的……没有错字(请参阅我的评论以回复他的回答)。

Monitor.java类:

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

电子邮件监视器.java

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

在此配置中,EmailMonitor.performMonitor()将始终在编译时检查它是否接收到EmailAccount列表,而不是我的任何其他类型的FTPAccount、DBAccount等...它比替代方案要干净得多,后者本来可以接收/发送原始列表,然后必须将其强制为所需的类型,从而导致潜在的运行时类型转换异常。

于 2008-10-27T14:59:27.577 回答