简体   繁体   English

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

[英]Java, Possible to modify method declaration of super class in abstract class hierarchy?

I have an abstract class UserdataUpdater which extends Updater 我有一个抽象类UserdataUpdater ,它扩展了Updater

Updater has a method declaration Updater具有方法声明

 public abstract void processRow (Cluster cluster, IAppendOnlyData row);

Is there anyway to modify this method declaration inside UserdataUpdater to make it more specific, like 无论如何,是否需要在UserdataUpdater修改此方法声明以使其更具体,例如

 public abstract void processRow (Cluster cluster, IUserData row);

IUserData extends IAppendOnlyData , because I want classes that extends UserdataUpdater to only take IUserData IUserData扩展了IAppendOnlyData ,因为我希望扩展UserdataUpdater类仅接受IUserData

No, you can't. 不,你不能。 This would break the contract of the superclass, which says: this method accepts a IAppendOnlyData as second argument. 这将破坏超类的约定,即:该方法接受IAppendOnlyData作为第二个参数。

Remember that an instance of a subclass is also an instance of its superclass. 请记住,子类的实例也是其超类的实例。 So anyone could refer to the subclass instance as its superclass, and call the base method, passing a IAppendOnlyData, without knowing that the instance is actually a subclass instance. 因此,任何人都可以将子类实例称为其超类,并通过传递IAppendOnlyData来调用基本方法,而无需知道该实例实际上是子类实例。

Read more about the Liskov substitution principle . 阅读有关Liskov替代原理的更多信息。

The only way to do that is to make the superclass generic: 唯一的方法是使超类通用:

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) {
        ...
    }
}

You cannot modify a method declaration in a derived class. 您不能在派生类中修改方法声明。 You can only override a superclass method if the derived class method has the exact same method signature. 如果派生类方法具有完全相同的方法签名,则只能覆盖超类方法。 You must use function overloading and make a new method processRow with the new parameter types you mentioned. 您必须使用函数重载,并使用您提到的新参数类型创建新方法processRow

In my experience, you have to use the first declaration, then in the implementation, check to make sure that: 以我的经验,您必须使用第一个声明,然后在实现中检查以确保:

row instanceof IUserData

of course, this is checked at runtime rather than during compile, but I don't know any other way around it. 当然,这是在运行时而不是在编译时检查的,但是我不知道有其他解决方法。 Of course, you can also just cast the row to the type IUserData, whether blindly or after checking its type (above). 当然,您也可以将行强制转换为IUserData类型,无论是盲目的还是在检查其类型之后(上面)。

Short answer: No. 简短答案:不可以。

You can create such a function, but because the signature is different, the compiler will see it as a different function. 您可以创建这样的函数,但是由于签名不同,因此编译器会将其视为不同的函数。

If you think about it, what you are trying to do doesn't really make sense. 如果您考虑一下,您尝试做的事情就没有任何意义。 Suppose you wrote a function that takes an Updater as a parameter and calls processRow on it with something that is not IUserData. 假设您编写了一个将Updater作为参数并使用非IUserData对其调用processRow的函数。 At compile time, Java has no way to know whether the object passed in an Updater, UserdataUpdater, or some other subclass of Updater. 在编译时,Java无法知道对象是通过Updater,UserdataUpdater还是其他某些Updater子类传递的。 So should it allow the call or not? 那么它应该允许呼叫吗? What should the compiler do? 编译器应该做什么?

What you can do is inside UserdataUpdater.processRow, include code that checks the type passed in at runtime and throws an exception or does some other sort of error processing if it is not valid. 您可以做的是在UserdataUpdater.processRow内部,包括检查运行时传递的类型并引发异常的代码,如果无效,则进行其他类型的错误处理。

Assuming you have no control on the Updater class, you can't do that ... you'll have to implement that method with the exact same signature. 假设您对Updater类没有控制权,那么您将无法做到这一点……您必须使用完全相同的签名来实现该方法。 However you can check for the type of row , inside your implementation and decide whatever processing is appropriate: 但是,您可以在实现中检查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