不使用类型测试,声明 doTheTask?

发布于 2024-12-23 18:54:51 字数 738 浏览 1 评论 0原文

我正在阅读 Cay Horstmann 编写的《Java For Every》。

当它说时我有点困惑:

不要使用类型测试

这是关于使用 instanceof 运算符进行特定类型测试,以实现随每个类而变化的行为,例如(直接取自书中):

if (q instanceof ChoiceQuestions) //Don't do this
{
   //Do the task the ChoiceQuestion way
}
else if (q instanceof Question)
{
   //Do the task Question way
}

显然这是一个糟糕的方法就好像您添加了一个像 NumericQuestion 这样的新类,您需要修改程序中进行类型测试的所有部分,添加另一个案例。

最好将类 NumericQuestion 添加到程序中。没有什么需要改变,因为我们使用的是多态性,而不是类型测试。 当您发现自己尝试在类层次结构中使用类型测试时,请重新考虑并使用多态性。在超类中声明一个方法doTheTask,在子类中重写它并调用q.doTheTask()

我不明白的是最后一段,即上面的一段。有人能给我举个例子来说明这意味着什么吗? (我是一个视觉学习者)。在不使用类型测试的情况下,我们如何实际做到这一点?

I'm going through Java For Everyone by Cay Horstmann.

I'm a bit confused on when it says:

Don't Use Type Tests

This is about using instanceof operator for specific type tests in order to implement behavior that varies with each class like (taken straight from the book):

if (q instanceof ChoiceQuestions) //Don't do this
{
   //Do the task the ChoiceQuestion way
}
else if (q instanceof Question)
{
   //Do the task Question way
}

Apparently this is a poor way to do it as if you have a new class like NumericQuestion added you need to revise all parts of your program that make a type test, adding another case.

It is better to add class NumericQuestion to the program. Nothing needs to change as we are using polymorphism, not type tests.
When ever you find yourself trying to use tyepe tests in a hierarchy of classes, reconsider and use polymorphism instead. Declare a method doTheTask in the superclass, override it in the subclasses and call q.doTheTask()

What I don't understand is the last paragraph, the one above. Can someone shoe me an example of what it means please? (I'm kind of a visual learner). How do we actually do this without using tyep tests?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(3

捂风挽笑 2024-12-30 18:54:51

重点是,而不是这样:

if (q instanceof ChoiceQuestions) //Don't do this
{
   //Do the task the ChoiceQuestion way
}
else if (q instanceof Question)
{
   //Do the task Question way
}

你应该这样做:

q.doTheTask();

其中 Question 类包含:

public void doTheTask(String someParameter){
    //Do the task Question way
}

并且 ChoiceQuestion 类包含

public void doTheTask(String someParameter){
    //Do the task the  ChoiceQuestion way
}

然后,当你得到一个新类 DrawQuestion 时,它将包含

public void doTheTask(String someParameter){
    //Do the task the DrawQuestionway
}

,但调用 doTheTask() 的代码都不必更改! 没有风险,因为 存在风险if (q 实例ChoiceQuestions) 模式,忘记添加新逻辑。而且(从长远来看,这实际上是更重要的部分)涉及特定类型问题的所有逻辑都集中在一个类中,而不是分散在应用程序的所有部分中。

The point is that instead of this:

if (q instanceof ChoiceQuestions) //Don't do this
{
   //Do the task the ChoiceQuestion way
}
else if (q instanceof Question)
{
   //Do the task Question way
}

you should do this:

q.doTheTask();

where the Question class contains:

public void doTheTask(String someParameter){
    //Do the task Question way
}

and the ChoiceQuestion class contains

public void doTheTask(String someParameter){
    //Do the task the  ChoiceQuestion way
}

Then, when you get a new class DrawQuestion, it will contain

public void doTheTask(String someParameter){
    //Do the task the DrawQuestionway
}

but none of the code that calls doTheTask() will have to change! There is no risk, as there is with the if (q instanceof ChoiceQuestions) pattern, of forgetting to add the new logic. And (this is actually the more important part in the long run) all the logic that concerns a specific kind of Question is concentrated in one class rather than spread out across all parts of the app.

那一片橙海, 2024-12-30 18:54:51

您应该理解的是,该类对其行为负责,而不是示例中的调用部分。我学到了“桌子应该自己画画”的原则:

可视化家具。你有一个油漆家具的油漆工类,但每次你声明一种家具时,你都必须“学习”它如何油漆一种新型家具。所以

Painter:

if (q instanceof Table) //Don't do this
{
   //paint table
}
else if (q instanceof Closet)
{
   //paint closet
}

你所做的就是让所有家具都扩展一个“家具”类,该类知道 paintThySelf() 方法。所以现在画家只需要做

q.paintThySelf()

,如果您添加一个 Chair 类,您将必须添加 paintThySelf() 方法,然后您就可以将其绘制出来。

What you should understand is that the class is responsible for its behaviour, not the calling part from the exmaple. I learned this as "a table should paint itself" principle:

Visualise furniture. You have a painter class that paints furniture, but you have to "learn" it how to paint a new type of furniture everytime you declare one. So

Painter:

if (q instanceof Table) //Don't do this
{
   //paint table
}
else if (q instanceof Closet)
{
   //paint closet
}

What you do is that you make all furniture extend a "furniture" class, that knows a method paintThySelf(). So now the painter just does

q.paintThySelf()

And if you add a Chair class, you will have to add the paintThySelf() method, and you can have it painted.

缪败 2024-12-30 18:54:51

作为设计原则,优先创建具有不同(覆盖)行为的子类,而不是使用 instanceof 来控制行为。

As a design principle, favour creating a subclass that has different (overridden) behaviour over using instanceof to control behaviour.

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