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

时间:2012-01-01 12:30:37

标签: java instance overrides

我正在通过Cay Horstmann的Java For Everyone。

当它说:

时,我有点困惑
  

不要使用类型测试

这是关于使用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添加到程序中。没有什么需要改变,因为我们使用多态,而不是类型测试。 当你发现自己试图在类的层次结构中使用tyepe测试时,重新考虑并使用多态。在超类中声明方法doTheTask,在子类中覆盖它并调用q.doTheTask()

我不明白的是最后一段,即上一段。有人可以给我一个例子吗? (我是一个视觉学习者)。我们如何在不使用tyep测试的情况下实际执行此操作?

3 个答案:

答案 0 :(得分:1)

你应该理解的是,班级负责其行为,而不是来自exmaple的呼叫部分。我将其理解为“一张桌子应该自己画画”的原则:

可视化家具。你有一个绘画家具的画家课程,但你必须“学习”每次申报时如何画一种新型家具。所以

画家:

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

你所做的就是让所有家具都延伸成一个“家具”类,它知道一种方法paintThySelf()。所以现在画家就是这样做了

q.paintThySelf()

如果您添加一个Chair类,则必须添加paintThySelf()方法,并且可以将其绘制。

答案 1 :(得分:1)

关键在于:而不是:

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 instanceof ChoiceQuestions)模式,忘记添加新的逻辑。而且(从长远来看,这实际上是更重要的部分)涉及特定类型Question的所有逻辑都集中在一个类中,而不是分散在应用程序的所有部分。

答案 2 :(得分:0)

作为一种设计原则,赞成创建一个具有不同(重写)行为的子类,而不是使用instanceof来控制行为。