如何调用子类中重写的方法?重构的潜在候选者
最初,我遇到了一个设计问题,我需要一个超类的五个子类,其中除了两个之外的所有子类都将使用相同的通用方法来执行操作,而其他两个类则需要特殊处理。我想避免将该方法编写五次;两个特殊情况和三个相同情况。
因此,我让每个类都继承 SuperClass 及其 doSomething() 方法,并使用 SubClassSpecial1 和 SubClassSpecial2 重写它们自己的 doSomeThing 方法。
这一切都很好,直到我编写了一个看起来像这样的方法
void fooBar(SuperClass obj) {
obj.doSomething()
}
,它可以被称为 fooBar( new SubClassSpecial1() );
问题是 obj 的运行时类> 变量现在是其超类的变量,因此它将调用超类中定义的方法。当然,我可以在超类中创建一个抽象的 doSometing() 方法,并使每个子类实现自己的版本,但这会在三个类中重复代码。我想避免这样做......
如果我有很多分支,我将失去多态性带来的任何增益
if(obj.getClass().getName() == "SubClassSpecial1" ) ((SubClassSpecial1) obj).doSomething()K;
else if ...
那么我应该做什么才能使设计更加优雅和不那么黑客呢?
Originally I had a design problem where I needed five subclasses of a superclass, where all but two would use the same generic method of doing things and the other two classes would need special handling. I wanted to avoid writing the method five times; two special cases and three identical ones.
So I had every class inherit SuperClass, and its doSomething() method, and had SubClassSpecial1 and SubClassSpecial2 override with their own doSomeThing method.
This was all fine until I wrote a method which looked something like
void fooBar(SuperClass obj) {
obj.doSomething()
}
and it could be called as fooBar( new SubClassSpecial1() );
The problem is that the runtime class of the obj
variable is now that of its superclass, and thus it will call the methods defined in the superclass. I could, of course, make an abstract doSometing() method in the superclass, and make each subclass implement its own version, but that would duplicate code in three of the classes. And I want to avoid doing that ...
I would lose any gain polymorphism gives if I had a lot of branching through
if(obj.getClass().getName() == "SubClassSpecial1" ) ((SubClassSpecial1) obj).doSomething()K;
else if ...
So what should I do in order to make the design more elegant and un-hackish?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我对你问题的这一部分有点困惑:
当然,声明并不重要,doSomething() 方法将始终根据类的运行时类型来调用。
所以我认为你想做的应该很好,例如这些声明都可以用来传递给 foobar 方法:
I'm a bit confused by this part of your question:
Ofcourse the declaration doesn't matter, the doSomething() method will always be invoked according to the runtime type of the class.
So I think what you were trying to do should work just fine, e.g. these declarations can all be used to pass to the foobar method:
你所描述的应该可以正常工作。
obj.doSomething() 实际上调用超类的实现吗?如果是,则说明您没有正确覆盖它。检查您是否未更改覆盖版本中的签名。
What you've described should work fine as is.
Is obj.doSomething() actually calling the superclass' implementation? If it is, you're not overriding it properly. Check that you haven't changed the signature in your overridden versions.
当你有这个:
那么
obj
的编译时类型是SuperClass
。这意味着编译器将检查SuperClass
是否具有doSomething()
方法。在运行时,您可以替换
SuperClass
的子类,这是里氏替换原则。方法foobar()
不知道也不应该知道obj
的运行时类型是什么,只是它派生自SuperClass
等等可以调用doSomething()
。至于您的示例:
在这种情况下,您碰巧知道参数的 runtime 类型是
SubClassSpecial1
,它专门覆盖doSomething()
。 在所有情况下都会调用正确的方法。关于重构的一句话。您可能需要考虑重构您的层次结构。
您的基类
SuperClass
应该将doSomething()
定义为抽象类。需要相同doSomething()
实现的三个类应该从具有该特定实现的中间基类继承它。您的两个特殊类应直接从SuperClass
继承,并拥有自己的doSomething()
实现。When you have this:
then the compile-time type of
obj
isSuperClass
. This means that the compiler is going to check thatSuperClass
has adoSomething()
method.At runtime you can substitute a subclass of
SuperClass
, this is the Liskov Substitution Principle. Methodfoobar()
does not know, and should not know, what the runtime type ofobj
is, only that it derives fromSuperClass
and sodoSomething()
can be called.As to your example:
In this case you happen to know that the runtime type of the parameter is
SubClassSpecial1
which specifically overridesdoSomething()
. In all cases the right method is called.A word about refactoring. You may want to consider refactoring your hierarchy.
Your base class
SuperClass
should definedoSomething()
as abstract. Your three classes that need the same implementation ofdoSomething()
should inherit it from an intermediate base class which has that specific implementation. Your two special classes should inherit directly fromSuperClass
and have their own implementation ofdoSomething()
.