Supposons que vous ayez besoin de définir une classe qui ne fait que contenir des constantes.
public static final String SOME_CONST = "SOME_VALUE";
Quelle est la meilleure façon de procéder?
- Interface
- Classe abstraite
- Classe finale
Lequel dois-je utiliser et pourquoi?
Clarifications à certaines réponses:
Enums - Je ne vais pas utiliser d'énumérations, je n'énumère rien, je collecte juste des constantes qui ne sont en aucun cas liées entre elles.
Interface - Je ne vais pas définir une classe comme une qui implémente l'interface. Je veux juste utiliser l'interface pour appeler des constantes comme ceci: ISomeInterface.SOME_CONST
.
java
class-constants
Yuval Adam
la source
la source
Réponses:
Utilisez un dernier cours. pour plus de simplicité, vous pouvez ensuite utiliser une importation statique pour réutiliser vos valeurs dans une autre classe
public final class MyValues { public static final String VALUE1 = "foo"; public static final String VALUE2 = "bar"; }
dans une autre classe:
import static MyValues.* //... if(variable.equals(VALUE1)){ //... }
la source
VALUE1.equals(variable)
car il évite NPE.Votre clarification stipule: "Je ne vais pas utiliser d'énumérations, je n'énumère rien, je ne fais que collecter des constantes qui ne sont en aucun cas liées les unes aux autres."
Si les constantes ne sont pas du tout liées les unes aux autres, pourquoi voulez-vous les rassembler? Mettez chaque constante dans la classe à laquelle elle est le plus étroitement liée.
la source
Mes suggestions (par ordre décroissant de préférence):
1) Ne le fais pas . Créez les constantes dans la classe réelle là où elles sont les plus pertinentes. Avoir une classe / interface «sac de constantes» ne suit pas vraiment les meilleures pratiques OO.
Moi et tout le monde, nous ignorons le n ° 1 de temps en temps. Si vous allez faire cela, alors:
2) classe finale avec constructeur privé Cela empêchera au moins quiconque d'abuser de votre «sac de constantes» en l'étendant / l'implémentant pour avoir un accès facile aux constantes. (Je sais que tu as dit que tu ne ferais pas ça - mais ça ne veut pas dire que quelqu'un vient après toi)
3) interface Cela fonctionnera, mais pas ma préférence en donnant la mention d'abus possible au n ° 2.
En général, ce n'est pas parce que ce sont des constantes que vous ne devriez pas toujours leur appliquer les principes oo normaux. Si personne d'autre qu'une classe ne se soucie d'une constante - elle doit être privée et dans cette classe. Si seuls les tests se soucient d'une constante, elle doit être dans une classe de test, pas dans du code de production. Si une constante est définie à plusieurs endroits (pas simplement accidentellement les mêmes) - refactoriser pour éliminer la duplication. Et ainsi de suite - traitez-les comme une méthode.
la source
Comme le note Joshua Bloch dans Effective Java:
Vous pouvez utiliser un Enum si toutes vos constantes sont liées (comme les noms de planètes), mettre les valeurs constantes dans les classes auxquelles elles sont liées (si vous y avez accès), ou utiliser une classe utilitaire non instanciable (définir un constructeur par défaut privé) .
class SomeConstants { // Prevents instanciation of myself and my subclasses private SomeConstants() {} public final static String TOTO = "toto"; public final static Integer TEN = 10; //... }
Ensuite, comme déjà indiqué, vous pouvez utiliser des importations statiques pour utiliser vos constantes.
la source
Ma méthode préférée est de ne pas le faire du tout. L'âge des constantes est pratiquement mort lorsque Java 5 a introduit les énumérations typesafe. Et même avant, Josh Bloch a publié une version (un peu plus verbeuse) de cela, qui fonctionnait sur Java 1.4 (et les versions antérieures).
À moins que vous n'ayez besoin d'une interopérabilité avec du code hérité, il n'y a plus aucune raison d'utiliser des constantes String / integer nommées.
la source
Utilisez simplement la classe finale.
Si vous souhaitez pouvoir ajouter d'autres valeurs, utilisez une classe abstraite.
Cela n'a pas beaucoup de sens d'utiliser une interface, une interface est censée spécifier un contrat. Vous souhaitez simplement déclarer des valeurs constantes.
la source
Les énumérations ne sont-elles pas le meilleur choix pour ce genre de choses?
la source
enum
s vont bien. IIRC, un élément en Java effectif (2e éd.) A desenum
constantes énumérant les options standard implémentant un [mot-clé Java]interface
pour n'importe quelle valeur.Ma préférence est d'utiliser un [mot-clé Java]
interface
plutôt qu'unfinal class
pour les constantes. Vous obtenez implicitement lepublic static final
. Certaines personnes soutiendront qu'uninterface
permet aux mauvais programmeurs de l'implémenter, mais les mauvais programmeurs vont écrire du code qui est nul, quoi que vous fassiez.Qu'est-ce qui a l'air mieux?
public final class SomeStuff { private SomeStuff() { throw new Error(); } public static final String SOME_CONST = "Some value or another, I don't know."; }
Ou:
public interface SomeStuff { String SOME_CONST = "Some value or another, I don't know."; }
la source
Ou 4. Placez-les dans la classe qui contient la logique qui utilise le plus les constantes
... désolé, je n'ai pas pu résister ;-)
la source
L'un des inconvénients du constructeur privé est que la méthode existe ne peut jamais être testée.
Enum par le concept de nature bon à appliquer dans un type de domaine spécifique, l'appliquer à des constantes décentralisées ne semble pas assez bon
Le concept d'énumération est «les énumérations sont des ensembles d'éléments étroitement liés».
Étendre / implémenter une interface constante est une mauvaise pratique, il est difficile de penser à l'exigence d'étendre une constante immuable au lieu de s'y référer directement.
Si vous appliquez un outil de qualité comme SonarSource, il existe des règles obligeant le développeur à abandonner l'interface constante, c'est une chose gênante car beaucoup de projets apprécient l'interface constante et voient rarement les choses «étendre» se produire sur des interfaces constantes
la source