instanceof是一个好的实践吗?

6
我有一个对象列表,这些对象都继承自一个基类。现在我想只对列表中的一个实例应用特定操作。
在这种情况下,使用 "instanceof" 好吗?还是应该使用自定义的 "enum" 来区分对象?
abstract class Base;
class Foo extends Base;
class Bar extends Base;

List<Base> bases;

for (Base base : bases) {
  if (base instanceof Bar.class) {
     //execute my custom operation on the base object
     doSomething((Bar) base);
  }
}

如果这种方法通常不是很好,我该怎么做得更好呢?

6
运用多态性,这也是其存在的原因。 - Oliver Charlesworth
你应该实现一些base.doSomething(),而不是使用doSomething(base)。在foo.doSomething()中重写它。请搜索Google多态性Java或Java覆盖方法。 - michael_s
3
如果你需要在添加枚举和使用instanceof之间进行选择,那么使用后者更好,因为它包含了与枚举相同的信息。 正如其他人所建议的,多态是Java的标准解决方案。然而,在许多情况下,您调用的并非全部代码都在您的控制范围内,使用instanceof是完全可以接受的。因此,真正的答案是:这取决于您在哪里使用它,以及是否有不需要您针对预定义类列表进行检查的替代方案。 - Darius X.
3个回答

3

在这里似乎没有使用实例的理由。当需要时,将基类默认行为更改为空,并在扩展类中进行覆盖可能是有意义的。这样,您只会在必要时进行覆盖(仅遵循本示例的问题所需的抽象类)。例如:

abstract class Base{
    public void doSomething(){}
}

public class B0 extends Base{
    @Override
    public void doSomething(){//actually do something}
} 

public class B1 extends Base{}

一个使用它的例子可以是这样的:
public class SomeOtherClass{
    public void something(List<Base> bases){
         for(Base base:bases)
             base.doSomething();
    }
}

这是一个非常好的想法,因为我可以省略那些在方法调用上什么都不做的类的实现。 - membersound

2
abstract class Base;//abstract function doSomething()
class Foo extends Base;//implements doSomething()
class Bar extends Base;//dito

List<Base> bases;

for (Base base : bases) {
     base.doSomething();
}

回答你的问题:使用 instanceof 不是一个好主意。

3
为什么现在要检查 instanceof?其实不必要。 - smk
2
语法错误,应该是 "base instanceof Bar"。 - shuangwhywhy
为什么你在使用instanceof,明明这不是一个好主意? - membersound
@SajitKunnumkal:复制粘贴错误。当然不需要! - Burkhard

1

这里使用“Instance of”不是一个好的实践。

正确的解决方案取决于doSomething方法内部发生了什么。如果你按照你的方式做,那么除了其他事情之外,你还违反了Liskov Substitution Principle。我假设你首先决定需要这些层次结构是因为某些原因,也假设子类型有比只有doSomething方法更多的行为。在这种情况下,您可以执行如下操作。基本上,只有应该doSomething的类型才会实际执行它,其余类型则执行类似于no operation的操作。通过这种方式,您可以使用这些对象,而无需知道它们真正的类型。

您还应该问自己是否真的需要将基类设置为抽象类。也许您只需要一个接口。可能有更好的方法,但根据我所拥有的信息和我的假设,这似乎是可以的。

public abstract class Base
{
    public abstract void doSomething();

    public void someOtherMethod()
    {
        // which does stuff
    }
}

public class SubTypeWhichCanDoSomething extends Base
{
    @Override
    public void doSomething()
    {
        // actually implement method and DO something
    }
}

public class DoesNothing extends Base
{
    @Override
    public void doSomething()
    {
        // does nothing
        return;
    }
}

// then your code looks like these
for(Base base : bases)
{
    base.doSomething();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接