[英]Java, Possible to modify method declaration of super class in abstract class hierarchy?
我有一个抽象类UserdataUpdater
,它扩展了Updater
Updater
具有方法声明
public abstract void processRow (Cluster cluster, IAppendOnlyData row);
无论如何,是否需要在UserdataUpdater
修改此方法声明以使其更具体,例如
public abstract void processRow (Cluster cluster, IUserData row);
IUserData
扩展了IAppendOnlyData
,因为我希望扩展UserdataUpdater
类仅接受IUserData
不,你不能。 这将破坏超类的约定,即:该方法接受IAppendOnlyData作为第二个参数。
请记住,子类的实例也是其超类的实例。 因此,任何人都可以将子类实例称为其超类,并通过传递IAppendOnlyData来调用基本方法,而无需知道该实例实际上是子类实例。
阅读有关Liskov替代原理的更多信息。
唯一的方法是使超类通用:
public class Updater<T extends IAppendOnlyData> {
...
public abstract void processRow(Cluster cluster, T row);
}
public class UserdataUpdater extends Updater<IUserData> {
@Override
public void processRow(Cluster cluster, IUserData row) {
...
}
}
您不能在派生类中修改方法声明。 如果派生类方法具有完全相同的方法签名,则只能覆盖超类方法。 您必须使用函数重载,并使用您提到的新参数类型创建新方法processRow
。
以我的经验,您必须使用第一个声明,然后在实现中检查以确保:
row instanceof IUserData
当然,这是在运行时而不是在编译时检查的,但是我不知道有其他解决方法。 当然,您也可以将行强制转换为IUserData类型,无论是盲目的还是在检查其类型之后(上面)。
简短答案:不可以。
您可以创建这样的函数,但是由于签名不同,因此编译器会将其视为不同的函数。
如果您考虑一下,您尝试做的事情就没有任何意义。 假设您编写了一个将Updater作为参数并使用非IUserData对其调用processRow的函数。 在编译时,Java无法知道对象是通过Updater,UserdataUpdater还是其他某些Updater子类传递的。 那么它应该允许呼叫吗? 编译器应该做什么?
您可以做的是在UserdataUpdater.processRow内部,包括检查运行时传递的类型并引发异常的代码,如果无效,则进行其他类型的错误处理。
假设您对Updater类没有控制权,那么您将无法做到这一点……您必须使用完全相同的签名来实现该方法。 但是,您可以在实现中检查row
的类型,并确定适当的处理方式:
public void processRow (Cluster cluster, IAppendOnlyData row)
{
if( row instanceof IUserData )
{
// your processing here
}
else
{
// Otherwise do whatever is appropriate.
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.