134 votes

Pourquoi ne pas utiliser protected static en java ?

Je me posais cette question Existe-t-il un moyen de remplacer les variables de classe en Java ? Le premier commentaire avec 36 votes était :

Si vous voyez un protected static , courir.

Quelqu'un peut-il expliquer pourquoi un protected static désapprouvé ?

6 votes

Il n'y a rien de mal à avoir un champ statique protégé, tant qu'il est final . Un champ statique mutable partagé entre plusieurs classes est une source d'inquiétude certaine. La mise à jour d'un champ statique par plusieurs classes ne sera probablement ni fiable ni facile à suivre, d'autant plus que la présence d'un champ ou d'une méthode protégés implique que la classe est destinée à être étendue par des classes d'autres paquets, éventuellement des classes qui ne sont pas sous le contrôle de l'auteur de la classe contenant le champ protégé.

6 votes

@VGR, final ne signifie pas que le champ est immuable. Vous pouvez toujours modifier le champ object référencé par un final variable de référence.

0 votes

@VGR Je ne suis pas d'accord. La SEULE raison pour laquelle vous créeriez une variable statique est d'y avoir accès à partir d'un autre paquet uniquement par héritage, et l'accès à un seul champ ne devrait PAS être la raison de l'héritage. C'est une conception erronée, IMO, et si vous y avez recours, vous devriez probablement repenser la structure de votre application. Mais ce n'est que mon avis.

94voto

Tim B Points 19851

Il s'agit plus d'une question de style que d'un problème direct. Cela suggère que vous n'avez pas bien réfléchi à ce qui se passe dans la classe.

Réfléchissez à ce que static signifie :

Cette variable existe au niveau de la classe, elle n'existe pas séparément pour chaque instance et il n'a pas d'existence indépendante dans les classes qui me prolongent .

Réfléchissez à ce que protected signifie :

Cette variable peut être vue par cette classe, les classes du même paquetage et les classes qui m'étendent .

Les deux significations ne s'excluent pas exactement l'une l'autre, mais c'est assez proche.

Le seul cas où l'on pourrait utiliser les deux ensemble est celui d'une classe abstraite conçue pour être étendue et dont la classe d'extension pourrait alors modifier le comportement en utilisant des constantes définies dans la classe d'origine. Ce type d'arrangement finirait très probablement par être très désordonné et indiquerait une faiblesse dans la conception des classes.

Dans la plupart des cas, il est préférable que les constantes soient publiques, car cela rend l'ensemble plus propre et offre plus de flexibilité aux personnes qui créent des sous-classes. Indépendamment de toute autre considération, dans de nombreux cas, la composition est préférable à l'héritage, tandis que les classes abstraites forcent l'héritage.

Pour voir un exemple de la façon dont cela pourrait casser les choses et pour illustrer ce que je veux dire par la variable n'ayant pas d'existence indépendante, essayez ce code d'exemple :

public class Program {
    public static void main (String[] args) throws java.lang.Exception {
        System.out.println(new Test2().getTest());
        Test.test = "changed";
        System.out.println(new Test2().getTest());
    }
}

abstract class Test {
    protected static String test = "test";
}

class Test2 extends Test {
    public String getTest() {
        return test;
    }
}

Vous verrez les résultats :

test
changed

Essayez-le vous-même sur le site : https://ideone.com/KM8u8O

La classe Test2 est capable d'accéder au membre statique test de Test sans avoir besoin de qualifier le nom - mais il n'hérite pas ou n'obtient pas sa propre copie. Il regarde exactement le même objet en mémoire.

4 votes

Vous êtes accrochés à l'héritage. Le cas typique est celui de quelqu'un qui veut accéder à un paquet sans le rendre public (par exemple, un test unitaire).

3 votes

@spudone mais les tests unitaires sont généralement placés dans le même paquet. Pour leur donner accès, il suffit d'utiliser le niveau d'accès par défaut (paquet). Protected donne également accès aux sous-classes, ce qui n'est pas nécessaire ou pertinent pour les tests unitaires.

0 votes

Bien qu'il réponde correctement à la question, je ne comprends pas personnellement cette ligne de code : Test.test = "changed"; . Comment le class Program être en mesure d'accéder à la base de données de l protégé attribut test ? Ne devrait-on pas protégé ne soient accessibles qu'aux enfants de l'attribut Test classe ? Ou bien c'est parce que la protégé est visible à partir de "classes dans le même paquet" comme indiqué ci-dessus ? (désolé si la question est stupide ; je ne connais presque pas Java)

34voto

Vince Emigh Points 1899

C'est mal vu parce que c'est contradictoire.

Création d'une variable protected implique qu'il sera utilisé dans le paquet ou il le sera hérité au sein d'une sous-classe .

Création de la variable static en fait un membre de la classe, en éliminant les intentions d'en hériter . Il ne reste plus que l'intention d'être utilisé à l'intérieur d'un paquet et nous avons package-private pour cela (sans modificateur).

La seule situation dans laquelle je pourrais trouver cela utile est celle où vous déclarez une classe qui doit être utilisée pour lancer l'application (comme la classe Application#launch et je voulais seulement pouvoir lancer un projet à partir d'une sous-classe. Dans ce cas, assurez-vous que la méthode est également final de refuser cacher . Mais ce n'est pas la "norme", et cela a probablement été mis en place pour éviter d'ajouter plus de complexité en ajoutant une nouvelle façon de lancer les applications.

Pour connaître les niveaux d'accès de chaque modificateur, voir ceci : The Java Tutorials - Contrôler l'accès aux membres d'une classe

5 votes

Je ne comprends pas comment static éliminer les intentions d'en hériter. Parce que ma sous-classe dans un autre paquetage exige toujours que le champ de super soit protected d'accès, même s'il s'agit d'une static . package-private ne peut pas aider

0 votes

@AoboYang Vous avez raison, c'est pourquoi certaines personnes utilisent protected static . Mais il s'agit d'une odeur de code, d'où la mention " courir Partie ". Les modificateurs d'accès et l'héritage sont deux sujets différents. Oui, vous ne pourrez pas accéder à un membre statique à partir d'une super classe s'il était package-private . Mais il ne faut pas compter sur l'héritage pour référencer les static C'est le signe d'une mauvaise conception. Vous remarquerez des tentatives de surcharge des champs static ne donnent aucun résultat, ce qui indique clairement que l'héritage n'est pas basé sur les classes. Si vous avez besoin d'un accès en dehors de la classe ou du paquetage, il doit être public

3 votes

J'ai une classe avec quelques private static mais je pense que quelqu'un pourrait vouloir améliorer ou personnaliser ma classe et que ces fonctions utilitaires pourraient lui être utiles. public n'est peut-être pas approprié car les méthodes util ne sont pas destinées à l'utilisateur des instances de ma classe. Pourriez-vous m'aider à trouver une bonne conception au lieu de protected ? Merci de votre compréhension.

15voto

Marco13 Points 14743

Je ne vois pas de raison particulière pour que cela soit désapprouvé. Il peut toujours y avoir des alternatives pour obtenir le même comportement, et cela dépendra de l'architecture actuelle si ces alternatives sont "meilleures" qu'une méthode statique protégée ou non. Mais un exemple où une méthode statique protégée serait raisonnable, au moins, pourrait être le suivant :

(édité pour être divisé en paquets séparés, afin de permettre l'utilisation de protected plus clair)

package a;
import java.util.List;

public abstract class BaseClass
{
    public Integer compute(List<Integer> list)
    {
        return computeDefaultA(list)+computeDefaultB(list);
    }

    protected static Integer computeDefaultA(List<Integer> list)
    {
        return 12;
    }
    protected static Integer computeDefaultB(List<Integer> list)
    {
        return 34;
    }
}

Dérivé de cela :

package a.b;

import java.util.List;

import a.BaseClass;

abstract class ExtendingClassA extends BaseClass
{
    @Override
    public Integer compute(List<Integer> list)
    {
        return computeDefaultA(list)+computeOwnB(list);
    }

    private static Integer computeOwnB(List<Integer> list)
    {
        return 56;
    }
}

Une autre classe dérivée :

package a.b;

import java.util.List;

import a.BaseClass;

abstract class ExtendingClassB extends BaseClass
{
    @Override
    public Integer compute(List<Integer> list)
    {
        return computeOwnA(list)+computeDefaultB(list);
    }

    private static Integer computeOwnA(List<Integer> list)
    {
        return 78;
    }
}

En protected static peut certainement être justifié ici :

  • Les méthodes peuvent être static car ils ne dépendent pas des variables d'instance. Elles ne sont pas destinées à être utilisées directement comme des méthodes polymorphes, mais sont plutôt des méthodes "utilitaires" qui offrent des fonctions par défaut de la mise en œuvre qui font partie d'un calcul plus complexe et servent de "blocs de construction" pour la mise en œuvre proprement dite.
  • Les méthodes ne doivent pas être public car il s'agit d'un détail de mise en œuvre. Et ils ne peuvent pas être private car elles doivent être appelées par les classes d'extension. Elles ne peuvent pas non plus avoir une visibilité "par défaut", car elles ne seraient alors pas accessibles aux classes d'extension dans d'autres paquets.

(EDIT : On peut supposer que le commentaire original ne se référait qu'aux champs et non à méthodes - mais il était alors trop général)

0 votes

Dans ce cas, vous devez définir les implémentations par défaut en tant que protected final (puisque vous ne voulez pas qu'ils soient remplacés), et non pas static . Le fait qu'une méthode n'utilise pas de variables d'instance ne signifie pas qu'elle doit être static (bien qu'il c ).

2 votes

Thomas Bien sûr, dans ce cas, ce serait également possible. En général : C'est certainement en partie subjectif, mais ma règle de base est la suivante : Lorsqu'une méthode n'est pas destinée à être utilisée de manière polymorphe et qu'elle peut être statique, je la rends statique. Contrairement au fait de la rendre final Il ne se contente pas d'indiquer clairement que la méthode n'est pas destinée à être remplacée. en plus indique clairement au lecteur que la méthode n'utilise pas de variables d'instance. En résumé : Il n'y a tout simplement aucune raison de no le rendre statique.

1 votes

Lorsqu'une méthode n'est pas destinée à être utilisée de manière polymorphe et qu'elle peut être statique, je la rends statique. - Cela vous posera des problèmes lorsque vous commencerez à utiliser des simulacres de frameworks pour les tests unitaires. Mais cela nous amène à un autre sujet ...

7voto

Bohemian Points 134107

Les membres statiques ne sont pas hérités et les membres protégés ne sont visibles que par les sous-classes (et bien sûr par la classe qui les contient). protected static a la même visibilité que static suggérant une incompréhension de la part du codeur.

1 votes

Pourriez-vous fournir une source pour votre première affirmation ? Dans un test rapide, un int statique protégé a été hérité et réutilisé dans une sous-classe sans problème.

0 votes

La statique protégée a la même visibilité que la statique privée par paquet, et non la statique privée. En outre, si vous utilisez protected et static, il est préférable de supprimer le modificateur d'accès pour le rendre privé (si votre intention est de le rendre accessible à l'intérieur du paquet).

2 votes

Euh ... non. paquet privé et protected ne sont pas les mêmes. Si vous dites simplement static le champ n'est visible que par les sous-classes du même paquetage.

4voto

Serge Ballesta Points 12850

Ce n'est pas une erreur d'avoir un static protected et elle sera acceptée par le compilateur Java. Mais la signification réelle est que il y aura une instance unique de la variable pour cette classe et toutes les classes dérivées .

Lorsque vous déclarez une variable non statique protégée, vous savez que chaque instance d'une classe dérivée aura sa propre copie de la variable. Et des programmeurs peu avertis pourraient vouloir utiliser une variable statique protégée dans le même sens : une copie pour chaque sous-classe - ce qui revient à dire qu'une variable statique protégée est une variable statique. erroné .

Autres cas d'utilisation courants (qui ne sont pas des erreurs) :

  • une constante qui ne devrait pas être publique - mais quelle peut être une bonne raison pour qu'une constante ne soit pas publique ? Si c'est pour des raisons de sécurité, cela suggère de mauvaises pratiques de sécurité ...
  • un suivi de tous les objets de cette classe, y compris les classes dérivées - mais il serait préférable d'avoir un objet conteneur, si jamais vous voulez avoir plus d'un groupe ...

IMHO c'est pourquoi protected static sont mal vus : ce n'est pas incorrect, mais de nombreux usages suggèrent de mauvaises pratiques.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X