在 Java 中使用通用参数覆盖方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/239645/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Overriding a method with Generic Parameters in Java?
提问by Robert Ngetich
I have an abstract Class Monitor.javawhich is subclassed by a Class EmailMonitor.java.
我有一个抽象类Monitor.java,它是由类EmailMonitor.java子类化的。
The method:
方法:
public abstract List<? extends MonitorAccount> performMonitor(List<? extends MonitorAccount> accounts)
is defined in Monitor.javaand must be overridden in EmailMonitor.java.
在Monitor.java 中定义并且必须在EmailMonitor.java 中覆盖。
I currently have the method overridden in EmailMonitor.javaas follows:
我目前在EmailMonitor.java 中重写了该方法,如下所示:
@Override
public List<EmailAccount> performMonitor(List<EmailAccount> emailAccounts) {
//...unrelated logic
return emailAccounts;
}
However, this produces the compile time error:
但是,这会产生编译时错误:
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
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
is a subclass of MonitorAccount
, so (in my mind at least) overriding it in this way makes perfect sense. Seeing as the compiler is not happy with my logic though, How should I go about this correctly while still keeping my compile time checks to make sure that all calls to EmailMonitor.performMonitor()
receive Lists of EmailAccount
rather than some other type of MonitorAccount
?
EmailAccount
是 的子类MonitorAccount
,所以(至少在我看来)以这种方式覆盖它是完全合理的。看到编译器对我的逻辑不满意,我应该如何正确地解决这个问题,同时仍然保持我的编译时检查以确保所有调用都是EmailMonitor.performMonitor()
接收列表的EmailAccount
而不是其他类型的MonitorAccount
?
采纳答案by Jon Skeet
No, it's not overriding it properly. Overriding means you should be able to cope with any valid input to the base class. Consider what would happen if a client did this:
不,它没有正确覆盖它。覆盖意味着您应该能够处理对基类的任何有效输入。考虑如果客户这样做会发生什么:
Monitor x = new EmailMonitor();
List<NonEmailAccount> nonEmailAccounts = ...;
x.performMonitor(nonEmailAccounts);
There's nothing in there which should give a compile-time error given your description - but it's clearly wrong.
根据您的描述,那里没有任何东西应该给出编译时错误 - 但这显然是错误的。
It sounds to me like Monitor
should be generic in the type of account it can monitor, so your EmailMonitor
should extend Monitor<EmailAccount>
. So:
在我看来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
}
}
You might want to think carefully about the generics in the performMonitor
call though - what's the return value meant to signify?
不过,您可能需要仔细考虑performMonitor
调用中的泛型——返回值意味着什么?
回答by Robert Ngetich
Here is my own solution. I suspect this is the same thing Jon Skeet was trying to get at... without the typo (see my comment in reply to his answer).
这是我自己的解决方案。我怀疑这与 Jon Skeet 试图解决的问题相同......没有打字错误(请参阅我对他的回答的评论)。
the Monitor.javaclass:
在Monitor.java类:
public abstract class Monitor <T extends MonitorAccount> {
...
public abstract List<T> performMonitor(List<T> accounts);
..
}
EmailMonitor.java
电子邮件监视器.java
public class EmailMonitor extends Monitor<EmailAccount> {
...
public List<EmailAccount> performMonitor(List<EmailAccount> emailAccounts) {
..//logic...logic...logic
return emailAccounts;
}
...
}
In this configuration, EmailMonitor.performMonitor()will always check at compile time that it receives a list of EmailAccountrather than any of my other types FTPAccount, DBAccount,etc... It's much cleaner than the alternative, which would have been receiving/sending a raw list and then having to coerce it the required type resulting in potential runtime type casting exceptions.
在此配置中,EmailMonitor.performMonitor()将始终在编译时检查它是否接收到一个EmailAccount列表,而不是我的任何其他类型的FTPAccount、DBAccount等......它比替代方案更清晰,后者本来会接收/发送原始列表,然后必须将其强制为所需类型,从而导致潜在的运行时类型转换异常。