web-dev-qa-db-fra.com

Quelle est l'utilisation des constantes d'interface?

J'apprends Java et viens de constater que l'interface peut avoir des champs, qui sont publics et définitifs. Je n'en ai pas vu d'exemples à ce jour. Quels sont quelques-uns des cas d'utilisation de ces constantes d’interface et puis-je en voir dans la Java Bibliothèque standard?

109
unj2

Mettre des membres statiques dans une interface (et implémenter cette interface) est une mauvaise pratique et il existe même un nom pour cette interface, Constant Interface Antipattern, voir Effective Java , élément 17:

Le modèle d'interface constant est une mauvaise utilisation des interfaces . Le fait qu'une classe utilise certaines constantes en interne est un détail d'implémentation. L'implémentation d'une interface constante entraîne la fuite de ces détails d'implémentation dans l'API exportée de la classe. Pour les utilisateurs d'une classe, le fait que celle-ci implémente une interface constante n'a pas d'importance. En fait, cela peut même les confondre. Pire, cela représente un engagement: si, dans une version ultérieure, la classe est modifiée de manière à ne plus utiliser les constantes, elle doit toujours implémenter l'interface pour assurer la compatibilité binaire. Si une classe non finale implémente une interface constante, toutes les sous-classes verront leurs espaces de noms pollués par les constantes de l'interface.

Il existe plusieurs interfaces constantes dans les Java de la plate-forme, telles que Java.io.ObjectStreamConstants. Ces interfaces doivent être considérées comme des anomalies et ne doivent pas être émulées.

Pour éviter certains pièges de l'interface constante (car vous ne pouvez pas empêcher les gens de l'implémenter), une classe appropriée avec un constructeur privé devrait être préférée (exemple emprunté à Wikipedia ):

public final class Constants {

    private Constants() {
        // restrict instantiation
    }

    public static final double PI = 3.14159;
    public static final double PLANCK_CONSTANT = 6.62606896e-34;
}

Et pour accéder aux constantes sans avoir à les qualifier complètement (c'est-à-dire sans avoir à les préfixer avec le nom de la classe), utilisez un importation statique (depuis Java 5):

import static Constants.PLANCK_CONSTANT;
import static Constants.PI;

public class Calculations {

    public double getReducedPlanckConstant() {
        return PLANCK_CONSTANT / (2 * PI);
    }
}
168
Pascal Thivent

" Le motif d'interface constant est une mauvaise utilisation des interfaces "

Quiconque a concocté cette hypothèse, quel que soit son statut de gourou, l’a concoctée sur la base de la nécessité de continuer à appliquer efficacement les mauvaises habitudes et les mauvaises pratiques. L'hypothèse est basée sur la promotion de la validité des mauvaises habitudes de conception de logiciels.

J'ai écrit ici une réplique de réponse contre cette hypothèse: Quel est le meilleur moyen d'implémenter des constantes en Java? expliquant le caractère sans fondement de cette hypothèse.

Pendant 10 ans, cette question était restée ouverte, jusqu'à ce qu'elle soit fermée dans les deux heures qui suivaient l'affichage de mes raisons, ce qui rendait cette hypothèse injustifiée, exposant ainsi UNWILLING au débat de ceux qui s'en tiennent à cette hypothèse erronée.

Ce sont les points que j'ai exprimés contre l'hypothèse

  • Cette hypothèse repose sur le besoin de méthodes et de règles RESTRICTIVE pour faire face aux effets de mauvaises habitudes et méthodologies logicielles.

  • Les partisans du sentiment " Le modèle d'interface constant est une mauvaise utilisation des interfaces" ne peut fournir aucune raison autre que celles causées par la nécessité de faire face avec les effets de ces mauvaises habitudes et pratiques.

  • Résoudre le problème fondamental.

  • Et ensuite, pourquoi ne pas utiliser pleinement et exploiter toutes les fonctionnalités linguistiques de la structure de langage Java à votre convenance. Pas de blouson requis. Pourquoi inventer des règles pour barricader votre style de vie inefficace afin de discriminer et incriminer des styles de vie plus efficaces ?

La question fondamentale

est l'organisation de l'information. Les informations véhiculées par le processus et le comportement de ces informations doivent d'abord être compris, de même que les règles métier, avant de concevoir ou de compléter des solutions. Cette méthode d'organisation de l'information s'appelait normalisation des données il y a quelques décennies.

Dans ce cas, seule l’ingénierie d’une solution peut être possible, car aligner la granularité et la modularité des composants d’une solution sur la granularité et la modularité des composants de l’information est la stratégie optimale.

Il existe deux ou trois obstacles importants à l’organisation de l’information.

  1. Le manque de perception du besoin de "normalisation" des modèles de données.

  2. Les déclarations de EF Codd sur la normalisation des données sont erronées, défectueuses et ambiguës.

  3. La dernière lubie se faisant passer pour une ingénierie agile est la notion erronée qu'il ne faut pas planifier et conditionner l'organisation des modules à l'avenir car vous pouvez la refactoriser au fur et à mesure. La refactorisation et le changement continu sans être gêné par les découvertes futures sont utilisés comme excuse. Les découvertes essentielles du comportement des informations de processus se font alors, en utilisant des astuces comptables permettant de retarder les bénéfices et la création d’actifs, raison pour laquelle les connaissances essentielles et leur traitement ne sont plus nécessaires.

L'utilisation de constantes d'interface est une bonne pratique.

Ne définissez pas de règles et n'émettez aucune fatwa à son encontre simplement parce que vous aimez vos habitudes de programmation ponctuelles aléatoires.

Ne pas interdire la possession d’armes à feu pour la raison qu'il existe des personnes qui ne savent pas manipuler les armes à feu ou qui sont susceptibles d’abuser des armes à feu.

Si les règles que vous concoctez sont conçues pour programmer des novices incapables de coder de manière professionnelle et que vous vous comptez parmi eux, dites-le. Ne déclarez pas votre fatwa comme applicable à des modèles de données correctement normalisés.

Un raisonnement idiot - Les interfaces de la langue Java) ne voulaient pas utiliser les interfaces de cette manière?

Je me fiche de ce que les intentions originales des pères fondateurs avaient pour la constitution américaine. Je me fiche des intentions non écrites non écrites. Je ne me soucie que de ce qui est littéralement codifié dans la Constitution écrite et de la façon dont je peux les exploiter pour le fonctionnement efficace de la société.

Je ne me soucie que de ce que les Java me permettent et que j’ai l’intention de exploiter pleinement pour me permettre d’exprimer mes solutions logicielles de manière efficace et efficiente. Aucune jaquette n’est requise.

L'utilisation de constantes Enum est en fait une pratique horrible.

Il faut écrire du code supplémentaire pour mapper le paramètre à la valeur. Le fait que les fondateurs de Java ne fournisse pas de mappage valeur-paramètre sans que vous écriviez ce code de mappage démontre que les constantes Enum constituent une utilisation non intentionnelle de Java .

Surtout que vous n'êtes pas encouragé à normaliser et à combiner vos paramètres, il y aurait une fausse impression que les paramètres mélangés dans un sac Enum appartiennent à la même dimension.

Les constantes sont des contrats API

N'oublie pas ça. Si vous avez conçu et normalisé votre modèle de données et qu'il inclut des constantes, ces constantes sont des contrats. Si vous n'avez pas normalisé votre modèle de données, vous devez vous conformer à la fatwas sur la façon de pratiquer un codage restrictif pour faire face à cette mauvaise habitude.

Par conséquent, les interfaces sont un moyen idéal pour mettre en œuvre le contrat de Constants.

Une présomption étrange - Que se passe-t-il si l'interface est implémentée par inadvertance?.

Ouaip. N'importe qui pourrait implémenter n'importe quelle interface par inadvertance. Rien ne s'opposera à ces programmeurs par inadvertance.

Concevez et normalisez votre modèle de données contre les fuites

Ne placez pas de décrets restrictifs pour protéger les mauvaises pratiques présumées qui entraînent une fuite des paramètres non contractés/égarés dans l'API. Résolvez le problème fondamental plutôt que d'imputer les constantes d'interface.

Ne pas utiliser un IDE est une mauvaise pratique

Un programmeur fonctionnant normalement et EFFECTIF n’est pas là pour prouver combien de temps elle peut rester sous l’eau, jusqu’à quelle distance elle pourrait marcher sous une chaleur torride ou des orages humides. Elle doit utiliser un outil efficace, comme une voiture, un bus ou au moins un vélo, pour se rendre au travail tous les 10 kilomètres.

Ne placez pas de restrictions sur les collègues programmeurs simplement parce que vous avez une obsession de l'ascétisme ésotérique avec la programmation sans IDE.

Quelques cadres sont conçus pour aider les programmeurs à continuer à mettre en pratique efficacement les mauvaises habitudes.

OSGI est un tel cadre. Il en va de même pour le décret contre les constantes d'interface.

Donc la réponse concluante ...

Les constantes d'interface constituent un moyen efficace de placer dans le contrat des composants bien conçus et normalisés d'un modèle de données.

Les constantes d'interface dans une interface privée nommée de manière appropriée et imbriquée dans un fichier de classe sont également une bonne pratique pour regrouper toutes vos constantes privées plutôt que de les disperser dans tout le fichier.

8
Blessed Geek

Joshua Bloch, "Effective Java - Guide du langage de programmation"):

Le modèle d'interface constant est une mauvaise utilisation des interfaces. Le fait qu'une classe utilise certaines constantes en interne est un détail d'implémentation. L'implémentation d'une interface constante entraîne la fuite de ces détails d'implémentation dans l'API exportée de la classe. Pour les utilisateurs d'une classe, le fait que celle-ci implémente une interface constante n'a pas d'importance. En fait, cela peut même les confondre. Pire, cela représente un engagement: si, dans une version ultérieure, la classe est modifiée de manière à ne plus utiliser les constantes, elle doit toujours implémenter l'interface pour assurer la compatibilité binaire. Si une classe non finale implémente une interface constante, toutes les sous-classes verront leurs espaces de noms pollués par les constantes de l'interface.

7
stacker

Je suis tombé sur cette vieille question à plusieurs reprises maintenant et la réponse acceptée me trouble encore. Après mûre réflexion, je pense que cette question peut être clarifiée davantage.

Pourquoi utiliser Interface Constant?

Il suffit de les comparer:

public final class Constants {

    private Constants() {
        // restrict instantiation
    }

    public static final double PI = 3.14159;
    public static final double PLANCK_CONSTANT = 6.62606896e-34;
}

contre

public interface Constants {

    public double PI = 3.14159;
    public double PLANCK_CONSTANT = 6.62606896e-34;
}

Même utilisation. Beaucoup moins de code.

Mauvaise pratique?

Je pense que la réponse de @Pascal Thivent a une mauvaise emphase, en voici ma version:

Mettre des membres statiques dans une interface (et implémenter cette interface) est une mauvaise pratique.

La citation de Effective Java) suppose que l'interface constante est implémentée par d'autres, ce qui, à mon avis, ne devrait pas (et ne se produira pas).

Lorsque vous créez une interface constante nommée quelque chose comme Constants, elle ne doit être implémentée par personne. (bien que techniquement possible, ce qui est le seul problème ici)

Cela n'arrivera pas dans la bibliothèque standard

La bibliothèque standard ne peut se permettre aucune utilisation abusive de la conception, vous ne pourrez donc en voir aucune.

Cependant, pour les projets quotidiens des développeurs normaux, l’utilisation de l’interface constantes est beaucoup plus simple car vous n’aurez pas à vous soucier de static, final, empty constructor, etc., et cela ne posera PAS de problème de conception. Le seul inconvénient auquel je puisse penser est qu’il porte toujours le nom "interface", mais rien de plus.

Un débat sans fin

À la fin, je pense que tout le monde ne fait que citer des livres et donner des opinions et des justifications à ses stands. Aucune exception pour moi. Peut-être que la décision appartient toujours aux développeurs de chaque projet. Allez-y, utilisez-le si vous vous sentez à l'aise. Le mieux que nous puissions faire est de le rendre cohérent tout au long du projet.

4
Nakamura

Ils sont utiles si vous avez des constantes communes qui seront utilisées dans les classes qui implémentent l'interface.

Voici un exemple: http://www.javapractices.com/topic/TopicAction.do?Id=32

Notez cependant que la pratique recommandée consiste à utiliser des importations statiques au lieu de constantes dans les interfaces. Voici une référence: http://www.javapractices.com/topic/TopicAction.do?Id=195

3
dcp

Il y a des réponses qui sont très raisonnables.

Mais j'ai quelques réflexions sur cette question. (peut être faux)

À mon avis, les champs d'une interface ne doivent pas être des constantes pour l'ensemble du projet, ils ne sont que des moyens pour l'interface et les interfaces l'étendent et les classes qui implémentent ces interfaces ou ont une relation étroite avec elles. Ils devraient être utilisés dans une certaine plage non globale.

2
Zhili

L’interface javax.swing.SwingConstants est un exemple qui contient des champs statiques utilisés par les classes swing. Cela vous permet d'utiliser facilement quelque chose comme

  • this.add(LINE_START, swingcomponent);
  • this.add(this.LINE_START, swingcomponent); ou
  • this.add(SwingComponents.LINE_START, swingcomponent);

Cependant cette interface n'a pas de méthodes ...

1
Progman

Je suis tombé sur cette question et j'ai pensé ajouter quelque chose qui n'a pas été mentionné. En général, je suis d'accord avec la réponse de Pascal ici . Cependant, je ne pense pas que les constantes sur une interface soient "toujours" un anti-modèle.

Par exemple, si les constantes que vous définissez font partie d'un contrat pour cette interface, l'interface est un excellent emplacement pour les constantes. Dans certains cas, il n’est pas approprié de valider en privé vos paramètres sans exposer le contrat aux utilisateurs de votre implémentation. Sans contrat public, les utilisateurs ne peuvent que deviner le contenu de votre validation, à moins de décompiler la classe et de lire votre code.

Ainsi, si vous implémentez une interface et que l'interface contient les constantes que vous utilisez pour garantir vos contrats (comme des plages entières, par exemple), un utilisateur de votre classe peut être sûr qu'il utilise correctement l'instance d'interface en vérifiant les constantes de l'interface. se. Cela serait impossible si les constantes étaient privées pour votre implémentation ou si votre implémentation était un paquet privé ou quelque chose du genre.

1
akagixxer

Deux points à propos de l'interface:

  • Une interface décrit n sous-ensemble de ce qu'un objet qui l'implémente peut le faire. (Ceci est l'intuition)

  • Une interface décrit constantes communes suivi de objets qui l'implémente.

    • Ces constantes communes sont destinées à être connues par le client pour en savoir plus sur ces objets.
    • Donc L'interface Constantes est en fait contre-intuitive pour définir constantes globales, car l'interface est utilisée pour décrire certains objets, pas tous les objets/aucun objet (considérons le sens de global ).

Donc, je pense que si Constantes L'interface n'est pas utilisée pour les constantes globales , alors c'est acceptable:

  • Si ces constantes communes ont de bons noms, ils vont recommander l'implémenteur pour les utiliser (voir mon premier point pour l'exemple ci-dessous)
  • Si une classe veut se synchroniser avec les classes qui suivent la spécification, il suffit de implements it (et, bien sûr, d'utiliser ces constantes communes dans la mise en œuvre).

Exemple:

interface Drawable {

    double GOLDEN_RATIO = 1.618033988;
    double PI = 3.141592653;
    ...

    // methods
    ...
}

public class Circle implements Drawable {
    ...
    public double getCircumference() {
        return 2 * PI * r;
    }
}

void usage() {

    Circle circle = new Circle(radius: 3.0);
    double maxRadius = 5.0;

    if ( circle.getCircumference() < 2 * Circle.PI * maxRadius ) {
        ...
    }

}

Dans cet exemple:

  • De Circle implements Drawable, vous savez immédiatement que Circle est probablement conforme aux constantes définies dans Drawable, sinon ils doivent choisir un nom plus mauvais que les bons PI et GOLDEN_RATIO a déjà été pris!
  • Seuls ces objets Drawable sont conformes aux spécificités PI et GOLDEN_RATIO défini dans Drawable, il peut exister des objets qui ne sont pas Drawable avec une précision différente de pi et du nombre d'or.