我有一个从基类扩展的对象列表。现在我想仅对列表中的一个类实例应用特定操作。
使用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);
}
}
如果这种方法一般不太好,我怎么能做得更好?
答案 0 :(得分:3)
似乎没有任何理由使用此处的实例。让基类默认行为无效并在需要时在扩展类中覆盖它可能是有意义的。这样你只需要在需要时覆盖它(我on.y把它留作抽象类来跟随这个例子不需要的问题)。 例如:
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();
}
}
答案 1 :(得分: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不是一个好主意。
答案 2 :(得分:1)
这里的实例不是一个好习惯。
正确的解决方案将取决于doSomething
方法内部究竟发生了什么。
如果你按照自己的方式行事,那么除了其他事情,你违反了Liskov Substitution Principle。我假设您决定首先需要这些层次结构,因为有些东西我也认为子类型比只有doSomething方法有更多的行为。在这种情况下,您可以执行的操作如下所示。基本上只有doSomething
实际执行此类型的类型,而其他类型的类型执行no operation
之类的操作。通过这种方式,您可以使用这些对象,而无需知道它们的实际类型。
您还应该问自己,您是否真的需要Base类是抽象类。也许你需要的只是一个界面。可能有更好的方法,但基于我所拥有的信息以及我所假设的信息,这似乎没有问题。
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();
}