2009-10-15 10 views
19

Ho due array: muri e vicini.È una pratica sbagliata usare il valore ordinale di Enum per indicizzare un array in Java?

public boolean[] walls = new boolean[4]; 
public Cell[] neighbors = new Cell[4]; 

e ho un Enum:

enum Dir 
{ 
    North, 
    South, 
    East, 
    West 
} 

Ora, mi piacerebbe essere in grado di accedere pareti o vicini di casa per la loro direzione, in modo da non dover passare intorno ad un gruppo di magia indici.

Tuttavia, quando stavo leggendo la documentazione di Enum.ordinal() diceva che i programmatori non avrebbero quasi più bisogno di questo metodo che mi ha fatto pensare che non dovrebbe essere usato in questo modo.

Stavo pensando di fare qualcosa di simile:

List<Dir> availableDirections = new ArrayList<Dir>(); 
    for(Dir direction : Dir.values()) 
     if (!Neighbors[direction.ordinal()].Visited) 
      availableDirections.add(direction); 

o anche:

return Neighbors[Dir.North.ordinal()]; 

Dovrei tornare a utilizzare le costanti statici per nord, sud, est, ovest con il valore di indice impostato loro o utilizzare il metodo ordinale di Enum?

risposta

16

Su una questione tangenziale, potrebbe essere meglio utilizzare un EnumMap per i vostri vicini:

Map<Dir, Cell> neighbours = 
    Collections.synchronizedMap(new EnumMap<Dir, Cell>(Dir.class)); 

neighbours.put(Dir.North, new Cell()); 

for (Map.Entry<Dir, Cell> neighbour : neighbours.entrySet()) { 
    if (neighbour.isVisited()) { ... } 
} 

etc.. 

BTW: Enumera istanze devono per convenzione essere scritto in maiuscolo,

enum Dir { 
    NORTH, 
    EAST, 
    SOUTH, 
    WEST 
} 
+2

E 'EnumSet' per' muri'. Probabilmente non ne ha bisogno per essere sincronizzato. –

13

La documentazione dice solo che il maggior parte dei programmatori non avrà alcuna utilità per il metodo. Questo è un caso di uso legittimo. Supponendo che la classe controlli sia l'enum che l'array, non c'è motivo di temere il metodo ordinal() per l'indicizzazione dell'array (poiché è sempre possibile mantenerli sincronizzati).

Tuttavia, se il tuo utilizzo diventa più complicato, è probabile che tu voglia utilizzare un EnumMap invece, come è stato suggerito.

+2

anche se questo è un caso valida con il codice riportato, la maggior parte del codice viene cambiato qualche tempo che può facilmente rendere una situazione non valido per esso. – pvgoddijn

1

Utilizzando ordinale di un enum per il tuo uso dipende dall'ordine implicito. Mi piace essere esplicito specialmente se si usano i valori interi come indice nel proprio array che collega il valore al significato.

In questo caso Vorrei quindi scegliere di utilizzare final static int NORTH = 0, ecc

13

Si può anche migliorare un enum (indice in senso orario):

enum Dir 
{ 
    NORTH(0), 
    SOUTH(2), 
    EAST(1), 
    WEST(3); 

    private final int index; 

    private Dir(int index) { 
    this.index = index; 
    } 

    public int getIndex() { 
    return index; 
    } 

} 
2

Se non siete le persistenti array o in qualsiasi altro il modo in cui ti stai rendendo dipendente da diverse versioni della tua classe enum, è sicuro usare ordinal().

Se si desidera non si vuole fare affidamento su l'ordinamento implicita dei valori enum, si potrebbe introdurre un valore di indice privato:

public enum Direction { 
    NORTH(0), 
    SOUTH(1), 
    EAST(2), 
    WEST(3); 

    private int _index; 

    private Direction (int index_) 
    { 
    _index = index_; 
    } 

    public int getIndex() 
    { 
    return _index; 
    } 
} 

Da qui è facile sia consentono una facile ricerca di indice per Direzione (creando una mappa in un blocco statico per una persistenza compatta, eseguire un controllo di unicità nel blocco statico, ecc.

3

Il JavaDoc dice

maggior parte dei programmatori avranno alcuna utilità per questo metodo. È progettato per essere utilizzato da strutture sofisticate di dati , come EnumSet e EnumMap.

Penso che vogliano dire che la maggior parte dei programmatori preferirà usare un EnumMap o EnumSet tramite l'indicizzazione manuale in un array. Certamente non significano che dovresti sostituire un paio di variabili intere per il tuo enum, dato che perderesti la sicurezza del tipo.

Se è necessaria la flessibilità per poter riordinare le costanti enum senza influire sull'ordine nell'array, è possibile isolare l'indice in un altro campo dell'enum come descritto da Arne.

1

raccomando fortemente contro di esso perché il valore di Ordinal è basato sull'ordine nel codice java.

L'uso di ordinal() renderà il codice molto difficile da mantenere, specialmente se qualche forma di persistenza entra nell'equazione.

ad esempio se si decide di aggiungere indicazioni diagonali come NORTH_WEST, SOUTH_EAST. se usi ordinal(), devi aggiungerli in fondo alla lista, altrimenti quello che prima era SUD potrebbe diventare NORD.

esempio, si può cambiare la vostra enyum a senza (forse) cambia la funzionalità

N (is now 0 was 0) 
NE (is now 1) 
E (is now 2 was 1) 
SE (is now 3) 
S (is mow 4 was 2) 
SW (is now 5) 
W (is now 6 was 3) 
Problemi correlati