2013-01-19 85 views
4

我正在創建一個遊戲。遊戲有一個GameMap。爲了跟蹤GameMap上的事物狀態,我想爲這些事情創建ArrayLists。問題是,我不想創建單獨的方法來添加或從每種類型的ArrayList中刪除項目。我當然是一個新手,所以我能想到的第一件事就是'instanceof'操作符。請記住,目前GameMap是一個離散的類,而不是一個接口或抽象類。其目的是在遊戲初始化時實例化一個GameMap對象。Java:添加或從列表中刪除元素時避免「instanceof」

public class GameMap { 

//GameMap has a name 
private String mapName; 

//GameMap has rooms 
private ArrayList<Room> roomsOnMap; 

//GameMap has items 
private ArrayList<Item> itemsOnMap; 

//GameMap has people 
private ArrayList<Person> peopleOnMap; 

//construct GameMap with rooms, items, and people 
private GameMap(String mapName, ArrayList someRooms, ArrayList someItems, ArrayList somePeople) 
{ 
    this.mapName = mapName; 
    this.roomsOnMap = someRooms; 
    this.itemsOnMap = someItems; 
    this.peopleOnMap = somePeople; 
} 

public void addObject(Object o) 
{ 
    //HOW DO I AVOID THIS? 
    if(o instanceof Room) 
    { 
     roomsOnMap.add((Room) o); 
    } 
    else if(o instanceof Item) 
    { 
     itemsOnMap.add((Item) o); 
    } 
    else if(o instanceof Person) 
    { 
     peopleOnMap.add((Person) o); 
    } 
} 
+7

我不明白爲什麼你不想單獨的方法。它會讓你的代碼更具可讀性。 – 11684

+0

每個對象,GameMap,Room,Item和Person都有ArrayList。這意味着對於每個對象,我必須編寫單獨的添加,刪除每種類型的ArrayList都重載的方法。我只是厭倦了打字。 –

+0

你或許可以通過1)複製粘貼2)一些智能IDE代碼生成來解決這個問題。 – 11684

回答

6

使用overloaded方法:

void addObject(Room room) { 
    roomsOnMap.add(room); 
} 

void addObject(Item item) { 
    itemsOnMap.add(item); 
} 

.. 
+1

不會推薦這個。爲什麼不用不同的方法這太容易出錯了 – Karussell

+1

你不會推薦函數重載嗎?我的意思是,它確實存在這個目的。 – Jack

+0

但是不易讀 – 11684

2

這裏有一個竅門:

Map<Class, ArrayList> map = new HashMap<Class, ArrayList>(); 
map.put(Room.class, roomsOnMap); 
map.put(Item.class, itemsOnMap); 
map.put(Person.class, peopleOnMap); 

// ... 

public void addObject(Object o) 
{ 
    map.get(o.getClass()).add(o); // be aware of NullPointerException here 
} 

雖然,我建議使用此重載方法。

+1

如果你調用addObject(new SubclassOfRoom())'會發生什麼?這不是一個好主意。它徹底打破了多態。 –

2

您預感到instanceOf可能不是一個很好的主意是正確的。

如果房間,物品和人員是某種「GameElements」或「MapElements」你可以通過一個共同的父它們之間的關係:

enum ElementType 
{ 
    PERSON, ITEM, ROOM; 
} 

interface MapElement 
{ 
    public ElementType getType(); 
} 

class Room implements MapElement 
{ 
    public ElementType getType() 
    { 
     return ElementType.ROOM; 
    } 
    //other attributes and methods... 
} 

class Person implements MapElement 
{ 
    public ElementType getType() 
    { 
     return ElementType.PERSON; 
    } 
    //other attributes and methods... 
} 

class Item implements MapElement 
{ 
    public ElementType getType() 
    { 
     return ElementType.ITEM; 
    } 
    //other attributes and methods... 
} 

然後你add方法可以在此界面

上運行
public void addObject(MapElement e) 
{ 
    if(e.getType == ElementType.Room) 
    { 
     roomsOnMap.add((Room) e); 
    } 
    ... 
} 

僅當元素相關時才這樣做。如果他們不是,你應該有單獨的方法。用單一的方法來做到這一點看起來很有效率,但你什麼也得不到。對於使用此類的任何類(以及編寫該類的開發人員),單獨添加方法(如果元素不相關)比使用Object作爲參數的通用添加更直觀。如果事實上你的類和方法變得更直接,你不會丟失任何東西,甚至不會有幾行代碼。

+0

這與OP現在所做的沒有什麼不同;語義。 –

+0

@AaronMcIver爲什麼不呢?問題是如何避免。 OP使用instanceOf是因爲他沒有看似相關的類之間的關係。 – Nivas

+0

我們在這裏失蹤的是我想實例化一個對象GameMap,以便我可以跟蹤遊戲中事物的狀態。但是這確實可以解決問題,因爲我可以創建一個名爲GameElements的接口,這樣我就可以從Room和Person類的每一箇中拉出重載的方法。 –