Si un ensemble de constantes être placé dans une classe ou interface?
si j'ai un ensemble de constantes statiques que je veux déclarer de façon centrale afin qu'elles puissent être partagées entre divers projets si elles sont mises dans une classe ou une interface (Java).
dans le passé je les ai vus la plupart du temps mis dans une classe mais j'ai commencé à penser que puisque la classe ne sera pas et ne devrait pas être instanciée peut-être ils seraient mieux dans une interface, mais encore une fois l'interface ne devrait pas être implémentée par des classes, par exemple
public class ErrorCodes {
public static final String ERROR_1 = "-1";
public static final String ERROR_2 = "-2";
}
ou
public interface ErrorCodes {
public static final String ERROR_1 = "-1";
public static final String ERROR_2 = "-2";
}
9 réponses
S'ils ont des liens forts, alors je les mettrais dans un enum:
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;
}
}
l'avantage est que vous pouvez avoir la sécurité de type dans votre code et que vous pouvez facilement ajouter id-based lookup (soit en construisant un HashMap<String,Error>
dans le constructeur ou simplement en bouclant au-dessus de values()
).
certaines personnes considèrent constante-interface un anti-modèle ( http://en.wikipedia.org/wiki/Constant_interface ).
vous devriez le faire dans une classe.
une Interface est une description des méthodes disponibles, des propriétés etc que les utilisateurs de classe peuvent accéder - en mettant en œuvre une interface, vous garantissez que les membres déclarés dans l'interface sont disponibles pour l'utilisateur.
d'Une classe, d'autre part, est une description d'un objet ou d' (si vous n'êtes pas trop dur sur l'OO principes...) un espace réservé pour les membres statiques. Je le trouve personnellement très utile dans certains projets pour stocker un tas de constantes dans une classe Settings
, donc je n'ai pas à regarder autour dans l'ensemble du projet pour les définitions. Je pense que cette approche est ce que vous cherchez, aussi.
l'utilisation de importation statique doit être considérée ici (pour les constantes d'importation définies dans une classe), ou type-safe Enum .
à Partir de de l'Interface pour les constantes
placer les constantes dans une interface était une technique populaire dans les premiers jours de Java, mais maintenant beaucoup considèrent qu'il est une utilisation désagréable de interfaces, puisque interfaces doivent traiter avec les services fournis par un objet, pas ses données .
De plus, les constantes utilisées par une classe sont typiquement un détail de mise en œuvre, mais les placer dans une interface Les promeut à l'API publique de la classe.
cela a été discuté avant :
la raison pour laquelle vous ne voulez pas des constantes dans une interface est qu'elle incite les classes de clients à" implémenter " cette interface (afin d'accéder aux constantes sans les préfixer avec le nom de l'interface). Vous ne devriez pas, cependant - l'interface n'est pas en fait une interface aux capacités de l'objet, mais une commodité de compilation ancrée dans le type externe de la classe.
il fut un temps où" l'interface constante "était très commode, mais elle a toujours été" erronée "et même la paresse n'est pas une excuse pour l'utiliser maintenant que nous avons import static
déclarations.
Edit: Même si je dois admettre que pour le scénario présenté dans votre question, les énumérations sont plus appropriés.
Vous devez les mettre sur la classe avec un constructeur privé.
public class ErrorCodes {
private ErrorCodes() {} // prevents instantiation
public static final String ERROR_1 = "-1";
public static final String ERROR_2 = "-2";
}
ou mieux encore, utilisez une police de sécurité enum.
je recommande une combinaison d'importations statiques et d'interfaces pour les constantes.
si une interface Java contient des déclarations de champ constantes, gardez à l'esprit qu'elles sont implicitement publiques, statiques et finales (voir la spécification Java Language, Section 9.3 ).) Vous pouvez donc toujours omettre ces modificateurs, en ne laissant que le type, et votre interface constante ressemblerait à ceci:
public interface Constants {
int AGE = 0x23;
String NAME = "Andrew";
boolean IGNORE = true;
}
Ceci devrait, bien sûr, seulement jamais être utilisé comme suit:
import static Constants.*;
public Whatever {
public String method() {
return String.format("%s is %d%c", NAME, AGE, IGNORE ? '?' : '!');
}
}
Je n'ai aucun problème à utiliser ce style dans mon code de production, et je pense qu'il conduit à une collection de constantes très soignée et compacte, et peut faire face à divers types de constantes, ce qu'un enum ne pourrait pas, en plus d'être capable d'être étendu si demandé, contrairement à un enum.
une autre possibilité, que tout le monde n'approuvera pas, est de nicher des interfaces (ou même enum types) dans votre interface parent, vous permettant de grouper vos constantes. Ceci:
interface MoreConstants {
int MAGIC = 0xCAFEBABE;
interface PROPERTIES {
String NAME = "name";
}
enum ERRORS {
ON_FIRE, ASLEEP, BROKEN, UNSURE;
}
}
et les Accéder comme ceci, en supposant une importation statique du MoreConstants interface:
if (!PROPERTIES.NAME.equals(value)) {
return ERRORS.UNSURE;
}
bien sûr, ces interfaces ne devraient jamais être mises en œuvre, ce que je considérerais comme une mauvaise pratique. La seule façon d'y parvenir, cependant, est de revoir strictement les codes...
je pense personnellement que les constantes doivent être définies dans une classe pour les mêmes raisons que celles décrites ci-dessus. Surtout parce que certains développeurs utilisent ces constantes en implémentant l'interface dans la classe qui veut les utiliser. Lorsque cette interface contient beaucoup de constantes, vous ne voulez plus regarder le javadoc de cette classe spécifique parce qu'il est jonché de descriptions de constantes qui ne sont probablement même pas utilisés par cette classe.
utiliser L'Interface pour les constantes est une bonne pratique. Mais vous ne voulez pas mettre en œuvre cette interface pour utiliser les constantes. Mais utilisez l'importation statique comme ci-dessous.
package com.data.job.spark;
public interface Constants {
/** base api url string literal. */
public static final String BASE_API_URL = "/api/v1";
/** message string literal. */
public static final String MESSAGE = "message";
/** exception string literal. */
public static final String EXCEPTION = "exception";
}
=================================
import static com.data.job.spark.Constants.EXCEPTION;
@Component("user360ToScyllaDbLoader")
public class TestConstants implements Serializable{
private static final long serialVersionUID = 1L;
}