2012-07-10 63 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

公開方法在超類,然後用壓倒一切的。在基類中提供一個空實現,以便子類可以在需要時忽略該操作。