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