如何知道某个特定对象是否属于某个类?

时间:2013-05-15 00:00:33

标签: java instanceof

我的课程中有以下课程:

public abstract class Question {

    private Topic topic;
    private String text;

    // methods

}

public class OpenQuestion extends Question {

    // methods

}

public class MultipleChoiceQuestion extends Question {

    private List<String> options = new ArrayList<String>();
    private String correct;

    // methods

}

此外,我还有另一个课程测试:

Question question;

// if the question is open

    if(question instanceof OpenQuestion) {

    ...

    }

// if the question is multiple choice

    if(question instanceof MultipleChoiceQuestion) {

    ...

    }

我正试图寻找instanceof的替代方案,因为我被告知它违反了OOP原则。

还有其他更好的方法可以知道问题是开放还是多项选择?

4 个答案:

答案 0 :(得分:4)

instanceof关键字本身不会破坏OOP原则。它们可能意味着你应该使用多态来执行逻辑。

而不是:

if(question instanceof OpenQuestion) {

...
}

//Countless ifs

if(question instanceof MultipleChoiceQuestion) {
...

}

你应该

question.doAction();

另一个例子(更明确):

abstract class Animal{
    public abstract void speak();
}

class Dog extends Animal{
    public void speak(){ System.out.println("Bark!"); }
}

class Cat extends Animal{
    public void speak(){ System.out.println("Meow!"); }
}

答案 1 :(得分:0)

当然你可以看到这个例子:

import java.lang.reflect.*;
import java.awt.*;

class SampleName {

public static void main(String[] args) {
Button b = new Button();
printName(b);
}

static void printName(Object o) {
   Class c = o.getClass();
   String s = c.getName();
   System.out.println(s);
}
}

答案 2 :(得分:0)

如果您对OO设计感兴趣,那么请考虑是否可以执行以下操作:让Question类调用一个方法,而不是if语句中的代码

public abstract class Question {
    private Topic topic;
    private String text;
    // methods
    public void abstract doSomething(Object arg);
}

public class OpenQuestion extends Question {
    @Override
    public void doSomething(Object arg) {
        // do something with an open question
    }
    // other methods
}

public class MultipleChoiceQuestion extends Question {
    private List<String> options = new ArrayList<String>();
    private String correct;
    @Override
    public void doSomething(Object arg) {
        // do something with an open question
    }
    // other methods
}

另一个类中的代码是:

Question question;
question.doSomething(arg);

为了传递Question对象不知道的任何信息,可以使用参数中的参数,但是当你想要做某事时,你可以使用它。

答案 3 :(得分:0)

它本身不是破坏OOP的实例,它知道你的类是什么特定类是一个打破它的实例。

如果你的班级是“动物”,可以是狗,猫或鸟... Animal.legs()应该足以在不知道动物类型的情况下计算腿部 - 当然这很容易。更难的情况是某些动物的方法对其他动物没有意义。

以不适用于狗或猫的案例fly()为例。在这种情况下,有一些解决方案,奇怪的是在这种情况下,instanceof可能是最好的!

您可以:   仅在鸟上实现fly()并反映鸟是否有fly()方法。   在每个类上实现canFly()和fly(),如果不能,则fly()抛出异常。

这些都不是好的 - 根本不是OO,无缘无故是丑陋和重复的(如果你有可用的鸭子,第一个也不错,但即便如此也不是最明显的解决方案)

那么什么是好的解决方案?有一个“Flies”接口声明了一个fly()方法,只有“Bird”实现了Flies。在这种情况下,instanceof是一个非常好的解决方案 - 可能是最好的!

坏:     如果(动物实体鸟)         ((鸟)动物).fly()

好:    如果(动物实例苍蝇)        ((蝇)动物).fly()

这是一个非常微妙的区别,直到你明白为什么 - 当你添加蝙蝠时会发生什么?在第一个你有:

if(animal instancef Bird)
    ((Bird)animal).fly()
else if(animal instancef Bat)
    ((Bat)animal).fly()

这是一个开关,构造,每当你发现自己用OO语言编写一个switch结构时,你可能做错了(这就是他们说instanceof错误的原因,因为它导致了switch结构)

只要Bat实现Flies,第二个示例仍然可以保持不变,并且将继续执行您实现的任何新对象。这太棒了。

使用接口这种方式比鸭子打字和反射更有优势 - 因为它具体而且经过深思熟虑。你不会不小心在Pants对象上调用.fly()并找回你没想到的Zipper,你可以检查“bat”的代码并轻松理解意图。