繁体   English   中英

Java,可以在抽象类层次结构中修改超类的方法声明吗?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM