2012-07-10 57 views
4

我有一个共同的超集的POJO。这些被存储在类型的二维阵列。现在,我想获得来自子类阵列和使用方法的对象。这意味着我必须将它们投射到子类。有没有办法做到这一点,而不使用instanceof避免的instanceof

更新:作为一个具体的例子:http://obviam.net/index.php/the-mvc-pattern-tutorial-building-games/参见:“添加新的行动(攻击)当敌人被点击”

+3

你为什么不想要一个instanceof的任何原因? – 2012-07-10 14:07:54

+3

或者为什么你不定义抽象方法(或接口),每个子类可以使用执行任何工作,你想干什么? – atk 2012-07-10 14:09:32

+0

是的。'instanceof'有点怪异,让我们来发掘一下更多的hacky吧。 – 2012-07-10 14:11:08

回答

4

如果您知道他们是子类型的,那么就在没有instanceof检查的情况下直接施放它们。

但是把它们放在一个超类型数组中是告诉编译器放弃它们实际上是子类型的信息。无论你的超应该揭露那些方法(也许是抽象的),或者你的阵列应该是子类型的(所以你不告诉编译器忘记的实际类型的对象),或者你必须吸上来并进行演员表(可能与instanceof测试)。

唯一的其他显着的替代方案是,你可能与访问者模式,它传递给目标的行动,让对象决定用它做什么实验。这使您可以重写类以忽略或根据其运行时类型执行操作。

6

是的 - 您可以通过颠倒流程来做到这一点:当基类的实例属于特定类型时,而不是代码执行某些操作,将操作项传递给对象,并让对象决定是否执行它与否。这是Visitor Pattern背后的基本技巧。

interface DoSomething { 
    void act(); 
} 
abstract class AbstractBaseClass { 
    abstract void performAction(DoSomething ds); 
} 
class FirstSubclass extends AbstractBaseClass { 
    public void performAction(DoSomething ds) { 
     ds.act(); 
    } 
} 
class SecondSubclass extends AbstractBaseClass { 
    public void performAction(DoSomething ds) { 
     // Do nothing 
    } 
} 

AbstractBaseClass array[] = new AbstractBaseClass[] { 
    new FirstSubclass() 
, new FirstSubclass() 
, new SecondSubclass() 
, new FirstSubclass() 
, new SecondSubclass() 
}; 
for (AbstractBaseClass b : array) { 
    b.performAction(new DoSomething() { 
     public void act() { 
      System.out.println("Hello, I'm here!"); 
     } 
    }); 
} 
+0

这是我最喜欢的方式。 **不幸的是**,我不能将方法添加到子类中,因为它们是没有任何功能的POJO。 – user28061 2012-07-10 14:28:13

+1

@ user28061如果你的子类没有覆盖,那么你的选择是quire有限的:所有的动作将被限制在作用在你的子类上的代码,所以你最终会得到一个'instanceof'。 – dasblinkenlight 2012-07-10 14:32:29

+2

POJO不能包含功能的整个概念在哪里出现?我在其他一些项目中看到了这一点。对象旨在包含数据和行为。如果他们只包含数据,他们不是pojos ...他们是豆类 – corsiKa 2012-07-10 17:15:34

2

您可以尝试使用Visitor设计模式。 http://en.wikipedia.org/wiki/Visitor_pattern

你要问自己,为什么你需要知道他们的类型,也许这可以通过使用超类的抽象方法来代替,他们每个人可以根据期望的结果执行。

abstract class A{ 
    abstract void visit(); 
} 

class B extends A{ 
    void visit() { print("B"); } 
} 

class C extends A { 
    void visit() { print("C"); } 
} 
1

我会避免将它们放在首位。

真的想想你想做什么,如果他们应该在这样的集合。

如果你有这样的事情

for(MyObj o : array) { 
    if(o instanceof A) { 
     ((A)o).doA(); 
    } 
    if(o instanceof B) { 
     ((B)o).doB(); 
    } 
} 

考虑这个,而不是

abstract class MyObj { 
    abstract void doIt(); 
} 

class A { 
    void doIt() { doA(); } 
} 

class B { 
    void doIt() { doB(); } 
} 
0

公开方法在超类,然后用压倒一切的。在基类中提供一个空实现,以便子类可以在需要时忽略该操作。