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



我有一个抽象类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,而不知道该实例实际上是一个子类实例。

阅读更多关于利斯科夫替代原理的信息。

唯一的方法是使超类泛型:

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 类型,无论是盲目还是在检查其类型(上图)后。

简短回答:不。

您可以创建这样的函数,但由于签名不同,编译器会将其视为不同的函数。

如果你仔细想想,你想做的事情并没有真正的意义。假设您编写了一个函数,该函数将更新程序作为参数,并使用非 IUserData 的内容对其调用 processRow。在编译时,Java无法知道对象是在Updater,UserdataUpdater还是Updater的其他子类中传递的。那么它应该允许通话吗?编译器应该怎么做?

您可以在 UserdataUpdater.processRow 中执行代码,这些代码检查在运行时传入的类型并引发异常,或者在无效时执行某种其他类型的错误处理。

假设您无法控制更新程序类,则无法执行此操作...您必须使用完全相同的签名实现该方法。但是,您可以在实现中检查row的类型,并决定适当的处理方式:

public void processRow (Cluster cluster, IAppendOnlyData row)
{
    if( row instanceof IUserData )
    {
        // your processing here
    }
    else
    {
        // Otherwise do whatever is appropriate.
    }
}

最新更新