如何调用子类中重写的方法?重构的潜在候选者

发布于 2024-08-09 11:11:38 字数 709 浏览 6 评论 0原文

最初,我遇到了一个设计问题,我需要一个超类的五个子类,其中除了两个之外的所有子类都将使用相同的通用方法来执行操作,而其他两个类则需要特殊处理。我想避免将该方法编写五次;两个特殊情况和三个相同情况。

因此,我让每个类都继承 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

甜心 2024-08-16 11:11:38

我对你问题的这一部分有点困惑:

当然,我想做的是让每个对象调用自己版本的 doSomething(),但没有意识到为了做到这一点,需要将 obj 声明为子类方法之一。现在一片混乱。

当然,声明并不重要,doSomething() 方法将始终根据类的运行时类型来调用。

所以我认为你想做的应该很好,例如这些声明都可以用来传递给 foobar 方法:

SuperClass sc1 = new SubClassSpecial1();
SubClassSpecial2 sc2 = new SubClassSpecial2();
//etc..

I'm a bit confused by this part of your question:

Of course, what I wanted to do was have each object call its own version of doSomething(), but failed to realise that in order to do that, obj needed to be declared as one of the subclassed methods. And now it's a mess.

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:

SuperClass sc1 = new SubClassSpecial1();
SubClassSpecial2 sc2 = new SubClassSpecial2();
//etc..
叹沉浮 2024-08-16 11:11:38

你所描述的应该可以正常工作。

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.

两相知 2024-08-16 11:11:38

当你有这个:

void fooBar(SuperClass obj) {
    obj.doSomething();
}

那么obj编译时类型是SuperClass。这意味着编译器将检查 SuperClass 是否具有 doSomething() 方法。
运行时,您可以替换SuperClass的子类,这是里氏替换原则。方法 foobar() 不知道也不应该知道 obj 的运行时类型是什么,只是它派生自 SuperClass 等等可以调用doSomething()

至于您的示例:

fooBar( new SubClassSpecial1() );

在这种情况下,您碰巧知道参数的 runtime 类型是 SubClassSpecial1 ,它专门覆盖 doSomething()在所有情况下都会调用正确的方法。

关于重构的一句话。您可能需要考虑重构您的层次结构。
您的基类 SuperClass 应该将 doSomething() 定义为抽象类。需要相同 doSomething() 实现的三个类应该从具有该特定实现的中间基类继承它。您的两个特殊类应直接从 SuperClass 继承,并拥有自己的 doSomething() 实现。

When you have this:

void fooBar(SuperClass obj) {
    obj.doSomething();
}

then the compile-time type of obj is SuperClass. This means that the compiler is going to check that SuperClass has a doSomething() method.
At runtime you can substitute a subclass of SuperClass, this is the Liskov Substitution Principle. Method foobar() does not know, and should not know, what the runtime type of obj is, only that it derives from SuperClass and so doSomething() can be called.

As to your example:

fooBar( new SubClassSpecial1() );

In this case you happen to know that the runtime type of the parameter is SubClassSpecial1 which specifically overrides doSomething(). 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 define doSomething() as abstract. Your three classes that need the same implementation of doSomething() should inherit it from an intermediate base class which has that specific implementation. Your two special classes should inherit directly from SuperClass and have their own implementation of doSomething().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文