我有一个抽象类UserdataUpdater
,它扩展了Updater
Updater
有一个方法声明
public abstract void processRow (Cluster cluster, IAppendOnlyData row);
无论如何都要在UserdataUpdater
中修改此方法声明以使其更具体,例如
public abstract void processRow (Cluster cluster, IUserData row);
IUserData
扩展了IAppendOnlyData
,因为我希望扩展UserdataUpdater
的类只能IUserData
答案 0 :(得分:13)
请记住,子类的实例也是其超类的实例。所以任何人都可以将子类实例称为其超类,并调用基本方法,传递IAppendOnlyData,而不知道该实例实际上是一个子类实例。
详细了解Liskov substitution principle。
这样做的唯一方法是使超类具有通用性:
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) {
...
}
}
答案 1 :(得分:1)
您无法修改派生类中的方法声明。如果派生类方法具有完全相同的方法签名,则只能覆盖超类方法。您必须使用函数重载并使用您提到的新参数类型创建新方法processRow
。
答案 2 :(得分:0)
根据我的经验,你必须使用第一个声明,然后在实现中检查以确保:
row instanceof IUserData
当然,这是在运行时而不是在编译期间检查的,但我不知道其他任何方式。当然,您也可以将行转换为IUserData类型,无论是盲目还是检查其类型(上图)。
答案 3 :(得分:0)
简短回答:不。
您可以创建这样的函数,但由于签名不同,编译器会将其视为不同的函数。
如果你仔细想想,你想要做的事情并没有多大意义。假设您编写了一个函数,该函数将Updater作为参数,并使用非IUserData调用processRow。在编译时,Java无法知道对象是否在Updater,UserdataUpdater或Updater的其他子类中传递。它应该允许通话吗?编译器应该做什么?
您可以在UserdataUpdater.processRow中执行的操作,包括检查在运行时传入的类型的代码,如果无效则抛出异常或进行其他类型的错误处理。
答案 4 :(得分:0)
假设您无法控制Updater类,则无法执行此操作...您必须使用完全相同的签名实现该方法。但是,您可以在实现中检查row
的类型,并确定适当的处理:
public void processRow (Cluster cluster, IAppendOnlyData row)
{
if( row instanceof IUserData )
{
// your processing here
}
else
{
// Otherwise do whatever is appropriate.
}
}