2009-10-15 11 views
19

Tengo dos matrices: Muros y Vecinos.¿Es una mala práctica usar el valor ordinal de Enum para indexar una matriz en Java?

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

y tengo una enumeración:

enum Dir 
{ 
    North, 
    South, 
    East, 
    West 
} 

Ahora, me gustaría ser capaz de acceder a las paredes o los vecinos por su dirección, por lo que no tiene que pasar alrededor de un montón de magia índices

Sin embargo, cuando estaba leyendo la documentación de Enum.ordinal() decía que los programadores casi no tendrían ningún uso para este método que me hizo pensar que no debería usarse de esta manera.

Yo estaba pensando en hacer algo como:

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

o incluso:

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

¿Debo volver a utilizar constantes estáticas para el norte, sur, este, oeste, con el valor del índice se establece en ellos o utilizar un método ordinal de Enum?

Respuesta

16

En un tema tangencial, tal vez sería mejor utilizar un EnumMap para sus vecinos:

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.. 

Por cierto: las instancias de enumeración deben por convención sea todo en mayúsculas,

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

Y 'EnumSet' para' walls'. Probablemente no es necesario que esté sincronizado. –

13

La documentación solo dice que la mayoría de los programadores no tendrán ningún uso para el método. Este es un caso de uso legítimo. Suponiendo que su clase controla tanto la matriz como la matriz, no hay razón para temer el método ordinal() para indexar la matriz (ya que siempre puede mantenerlos sincronizados).

Sin embargo, si su uso se vuelve más complicado, es probable que desee utilizar un EnumMap en su lugar, como se ha sugerido.

+2

pesar de que este es un caso válido con el código que se muestra, la mayoría del código se cambia en algún momento que puede fácilmente hacer que una situación no válida para ello. – pvgoddijn

1

Usando ordinal de una enumeración para su uso depende del orden implícito. Me gusta ser explícito, especialmente si usa los valores enteros como índice en su matriz, vinculando el valor al significado.

En este caso, por tanto, me gustaría optar por usar final static int NORTH = 0, etc.

13

También puede mejorar una enumeración (en sentido horario índice):

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

Si no está persistiendo los arrays o en cualquier otro De esta manera, al hacerse dependiente de las diferentes versiones de su clase enum, es seguro usar ordinal().

Si desea no quieren confiar en el orden implícito de los valores de enumeración, se puede introducir un valor de índice privada:

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; 
    } 
} 

Desde aquí es fácil tanto permiten una fácil de búsqueda de índice para Dirección (Creando un Mapa en un bloque estático para persistencia compacta; Hacer verificación de unicidad en bloque estático, etc.

3

el Javadoc dice

mayoría de los programadores tendrán ningún uso para este método. Está diseñado para ser utilizado por sofisticadas estructuras de datos basados ​​en enumeración , tales como EnumSet y EnumMap.

Creo que quieren decir que la mayoría de los programadores preferirán usar EnumMap o EnumSet para indexar manualmente en una matriz. Ciertamente no significa que deba sustituir un par de variables enteras por su enumeración, ya que perdería seguridad de tipo al hacerlo.

Si necesita la flexibilidad para poder reordenar las constantes enum sin afectar el orden en la matriz, puede aislar el índice en otro campo de la enumeración como ha sido descrito por Arne.

1

lo recomiendo encarecidamente porque el valor ordinal se basa en el orden de su código java.

El uso de ordinal() hará que el código sea muy difícil de mantener, especialmente si alguna forma de persistencia entra en la ecuación.

por ejemplo si decide agregar direcciones diagonales como NORTH_WEST, SOUTH_EAST. si está utilizando ordinal(), debe agregarlos en la parte inferior de la lista o, de lo contrario, lo que solía ser SOUTH podría convertirse en NORTH.

es decir, cambiar su enyum a sin (posiblemente) la funcionalidad de cambio de

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) 
Cuestiones relacionadas