2009-09-03 22 views
26

Si tengo una colección de constantes estáticas que deseo declarar centralmente para que se puedan compartir entre varios proyectos, deben colocarse en una clase o interfaz (Java).¿Debería colocarse una colección de constantes en una clase o interfaz?

En el pasado los he visto colocar en su mayoría en una clase, pero comencé a pensar que dado que la clase no se instanciará y quizás no deberían ser mejores en una interfaz, la interfaz no debería ser implementada por cualquier clase, por ejemplo

public class ErrorCodes { 
    public static final String ERROR_1 = "-1"; 
    public static final String ERROR_2 = "-2"; 
} 

o

public interface ErrorCodes { 
    public static final String ERROR_1 = "-1"; 
    public static final String ERROR_2 = "-2"; 
} 

Respuesta

27

Si tienen conexiones fuertes, entonces yo ponerlos en una enumeración:

public enum Error { 
    ERROR_1("-1", "foo went wrong"), 
    ERROR_2("-2", "bar went wrong"); 

    private final String id; 
    private final String message; 

    Error(String id, String message) { 
    this.id=id; 
    this.message=message; 
    } 

    public String getId() { 
    return id; 
    } 

    public String getMessage() { 
    return message; 
    } 
} 

La ventaja es que se puede tener la seguridad de tipos en el código y que puede agregar fácilmente la búsqueda basada en el id (ya sea construyendo un HashMap<String,Error> en el constructor o simplemente haciendo un círculo sobre values()).

+0

Una enumeración es en realidad una forma mejor de hacerlo. Supongo que no leí su pregunta con cuidado para captar sus intenciones ... –

+1

Encontré que esta es la mejor solución, ya que puede mantener los números y las cadenas juntas y cargar las cadenas desde un archivo de propiedades. Todo en un mismo lugar. –

+0

¿Sigue siendo este el mejor método si tiene una gran cantidad de constantes o afecta el rendimiento después de cierto punto? – Yonetmen

4

Deberías hacerlo en una clase.

Una interfaz es una descripción de los métodos disponibles, propiedades, etc. a los que pueden acceder los usuarios de clase: al implementar una interfaz, garantiza que los miembros declarados en la interfaz están disponibles para el usuario.

Una clase, por otro lado, es una descripción de un objeto o (si no es demasiado hard on the OO principles ...) un marcador de posición para miembros estáticos. Personalmente, me resulta muy útil en algunos proyectos almacenar un montón de constantes en una clase Settings, por lo que no tengo que buscar en todo el proyecto las definiciones. Creo que este enfoque es lo que buscas, también.

+0

Recoge tus constantes dentro de una clase y dale un constructor privado para evitar que se cree una instancia. –

5

El uso de static import deben ser considerados aquí (para importar constantes definidas en una clase), o type-safe Enum.

De Interface for constants

La colocación de las constantes en una interfaz era una técnica popular en los primeros días de Java, pero ahora muchos lo consideran un uso mal gusto de interfaces, ya que interfaces deben hacer frente a los servicios prestados por una objeto, no sus datos.
Además, las constantes utilizadas por una clase suelen ser un detalle de implementación, pero colocarlas en una interfaz las promueve a la API pública de la clase.

2

Deberías ponerlos en la clase con un constructor privado.

public class ErrorCodes { 
    private ErrorCodes() {} // prevents instantiation 
    public static final String ERROR_1 = "-1"; 
    public static final String ERROR_2 = "-2"; 

}

O mejor aún, utilizar una enumeración de seguridad de tipos.

5

Esto ha sido discutido before:

La razón por la que no quiere las constantes en una interfaz es que atrae a clases de cliente a "aplicar" esa interfaz (con el fin de acceder a las constantes y sin prefijar ellos con el nombre de la interfaz). No deberías, sin embargo, que la interfaz no sea realmente una interfaz para las capacidades del objeto, sino una conveniencia de tiempo de compilación arraigada en el tipo externo de la clase.

Hubo un momento en que la "interfaz constante" era muy conveniente, pero siempre ha sido "malo" y ni siquiera la pereza es una excusa para usarlo ahora que tenemos import static declaraciones.

Edit: Aunque debo aceptar que para el escenario presentado en su pregunta, las enumeraciones son más apropiadas.

7

Algunas personas consideran que la interfaz constante es un antipatrón (http://en.wikipedia.org/wiki/Constant_interface).

+4

En mi opinión, el antipatrón es * la implementación * de una interfaz con el fin de obtener acceso a las constantes con nombre. –

0

Personalmente creo que las constantes deben definirse en una clase por las mismas razones que las descritas anteriormente. Especialmente porque algunos desarrolladores usan estas constantes implementando la interfaz en la clase que quiere usarlos. Cuando esa interfaz contiene muchas constantes, ya no quiere ver el javadoc de esa clase específica porque está llena de descripciones de constantes que ni siquiera son utilizadas por esa clase.

2

Recomiendo una combinación de importaciones estáticas e interfaces para constantes.

Si una interfaz Java tiene declaraciones de campo constante, ten en cuenta que estos son implícitamente pública, estático y final (véase el Java Language Specification, Section 9.3). Es, por tanto, siempre se puede omitir estos modificadores, dejando sólo el tipo, y su interfaz constante se vería así:

public interface Constants { 
    int AGE = 0x23; 
    String NAME = "Andrew"; 
    boolean IGNORE = true; 
} 

esto se debe, por supuesto, solamente nunca ser utilizado de la siguiente manera:

import static Constants.*; 

public Whatever { 
    public String method() { 
     return String.format("%s is %d%c", NAME, AGE, IGNORE ? '?' : '!'); 
    } 
} 

No tengo problemas para usar este estilo en mi código de producción, y creo que conduce a una colección de constantes muy ordenada y compacta, y puede hacer frente a varios tipos de constantes, que una enumeración no pudo, además de poder extenderse si se requiere, a diferencia de una enumeración.

Otra posibilidad, que no todo el mundo aprobará, es anidar las interfaces (o incluso los tipos enum) en su interfaz principal, lo que le permite agrupar sus constantes. Este:

interface MoreConstants { 
    int MAGIC = 0xCAFEBABE; 
    interface PROPERTIES { 
     String NAME = "name"; 
    } 
    enum ERRORS { 
     ON_FIRE, ASLEEP, BROKEN, UNSURE; 
    } 
} 

y acceder a ellas como este, asumiendo una importación estática de los MoreConstants interfaz:

if (!PROPERTIES.NAME.equals(value)) { 
    return ERRORS.UNSURE; 
} 

Por supuesto, nunca se deben implementar estas interfaces, lo que yo consideraría una mala práctica. La única manera de asegurar esto, sin embargo, es estrictas revisiones de código ...

+0

Un problema que no tocas es que algunas constantes se copiarán en tiempo de compilación en el bytecode generado en lugar de ser referenciadas, dejándote con un ABI que no puedes cambiar sin romper cosas. –

+0

¿No es esto también un problema con la solución 'class for constants', debido al acceso directo al campo? – grkvlt

+0

Sí, creo que ocurre lo mismo para la clase y la interfaz, pero podría estar equivocado. +1 a las respuestas enum –

Cuestiones relacionadas