Pourquoi nous ne devrions pas utiliser les statiques protégés en java

je passais en revue cette question y a-t-il un moyen d'outrepasser les variables de classe en Java? Le premier commentaire avec 36 upvotes était:

si vous voyez un protected static , courez.

est-ce que quelqu'un peut expliquer pourquoi un protected static est mal vu?

106
demandé sur Community 2014-06-18 19:09:05

8 réponses

c'est plus une question de style qu'un problème direct. Cela suggère que vous n'avez pas bien réfléchi à ce qui se passe avec la classe.

pensez à ce que static signifie:

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

penser sur ce que protected signifie:

cette variable peut être vue par cette classe, les classes dans le même paquet et les classes qui s'étendent me .

les deux significations ne s'excluent pas mutuellement, mais elles sont assez proches.

le seul cas où je peux voir où vous pourriez utiliser les deux ensemble est si vous aviez une classe abstraite qui a été conçu pour être étendu et la classe d'extension pourrait alors modifier le comportement en utilisant des constantes définies dans l'original. Même alors c'est une raison très faible bien que vous seriez encore presque certainement mieux avoir les constantes en tant que public. Cela rend tout simplement plus propre et permet aux personnes subclassant plus de flexibilité.

pour développer et expliquer le premier point-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 vous-même à: https://ideone.com/KM8u8O

la classe Test2 peut accéder au membre statique test de Test sans avoir besoin de qualifier le nom - mais il n'hérite pas ou obtenir sa propre copie. Il est à la recherche exactement à la même variable.

66
répondu Tim B 2015-11-13 22:49:31

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

la réalisation d'une variable protected implique qu'elle sera utilisée dans le paquet ou qu'elle sera héritée dans une sous-classe .

apporter de la variable "151910920 en fait un membre de la classe, , éliminant les intentions de héritage . Cela ne laisse que l'intention d'être utilisé dans un paquet , et nous avons package-private pour cela (pas de modificateur).

la seule situation pour laquelle je pourrais trouver cela utile est si vous déclariez une classe qui devrait être utilisée pour lancer l'application (comme Application#launch de JavaFX , et ne voulait être en mesure de lancer à partir d'une sous-classe. Si c'est le cas, s'assurer que la méthode est aussi final pour rejeter Cacher . Mais ce n'est pas" la norme", et a probablement été mis en œuvre pour éviter d'ajouter plus de complexité par l'ajout d'une nouvelle façon de lancer des applications.

pour voir les niveaux d'accès de chaque modificateur, voir ceci: les tutoriels Java-contrôler L'accès aux membres d'une classe

26
répondu Vince Emigh 2016-08-04 17:04:28

je ne vois pas de raison particulière pourquoi cela devrait être désapprouvé. Il peut toujours y avoir des alternatives pour obtenir le même comportement, et cela dépendra de l'architecture réelle 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:

(révisé pour être divisé en paquets séparés, pour rendre l'utilisation de protected plus claire)

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;
    }
}

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;
    }
}

le protected static modificateur peut certainement être justifié ici:

  • les méthodes peuvent être static , parce qu'elles ne dépendent pas des variables d'instance. Ils ne sont pas destinés à être utilisés directement comme une méthode polymorphe, mais sont plutôt des méthodes "utilitaire" qui offrent des implémentations par défaut qui font partie d'un calcul plus complexe, et servent de" composantes de base " de la mise en œuvre réelle.
  • les méthodes ne devraient pas être public , car elles sont un détail de mise en œuvre. Et ils ne peuvent pas être private parce qu'ils devraient être appelés par les classes extensives. Ils ne peuvent pas non plus avoir de visibilité "par défaut", parce qu'ils ne seront pas accessibles pour les classes extending dans d'autres paquets.

(EDIT: On pourrait supposer que le commentaire original ne faisait référence qu'aux" champs 1519210920", et non aux "méthodes 1519210920" - alors, cependant, il était trop général)

11
répondu Marco13 2014-06-18 15:40:43

les éléments statiques ne sont pas hérités, et les éléments protégés ne sont visibles que pour les sous-classes (et bien sûr la classe contenant), de sorte qu'un protected static a la même visibilité que static , ce qui suggère un malentendu par le codeur.

7
répondu Bohemian 2014-06-18 15:21:33

Protégé est utilisé de sorte qu'il peut être utilisé dans des sous-classes. Il n'y a pas de logique dans la définition d'une statique protégée lorsque l'on utilise dans le contexte de classes concrètes car vous pouvez accéder à la même variable est une manière statique.Cependant, le complier donnera un avertissement pour accéder à la variable statique super class d'une manière statique.

3
répondu Mithun Kannoth 2014-06-18 15:38:51

en fait, il n'y a rien de fondamentalement mauvais avec protected static . Si vous voulez vraiment une variable statique ou une méthode qui est visible pour le paquet et toutes les sous-classes de la classe déclarante alors allez-y et faites protected static .

certaines personnes évitent généralement d'utiliser protected pour diverses raisons et certaines personnes pensent que les variables non-finales static devraient être évitées par tous les moyens (je compatis personnellement à ces derniers dans une certaine mesure), donc je suppose que le combinaison de protected et static doit regarder mauvais^2 que ceux qui appartiennent aux deux groupes.

3
répondu x4u 2014-06-18 22:44:52

il n'y a pas de mal à avoir protected static . Une chose que beaucoup de gens négligent est que vous pouvez vouloir écrire des cas de test pour les méthodes statiques que vous ne voulez pas exposer dans des circonstances normales. J'ai remarqué que c'est particulièrement utile pour écrire des tests pour la méthode statique dans les classes d'utilité.

0
répondu Aelphaeis 2016-07-05 15:34:02

eh Bien, comme la plupart des gens ont répondu:

  • protected signifie - ' paquet-privé + visibilité vers les sous - classes-la propriété/le comportement est hérité '
  • static signifie - le contraire de l'instance - il s'agit d'une propriété/comportement de classe, I. e il N'est pas hérité

par conséquent, ils sont légèrement contradictoires et incompatible.

Cependant, récemment, je suis venu à un cas d'utilisation où il pourrait être judicieux d'utiliser les deux ensemble. Imaginez que vous voulez créer une classe abstract qui est un parent pour les types immuable et il a un tas de propriétés qui sont communes aux sous-types. Pour mettre en œuvre immutabilité correctement et garder lisibilité on pourrait décider d'utiliser le Constructeur modèle.

package X;
public abstract class AbstractType {
    protected Object field1;
    protected Object field2;
    ...
    protected Object fieldN;

    protected static abstract class BaseBuilder<T extends BaseBuilder<T>> {
    private Object field1; // = some default value here
    private Object field2; // = some default value here
    ...
    private Object fieldN; // = some default value here

    public T field1(Object value) { this.field1 = value; return self();}
    public T field2(Object value) { this.field2 = value; return self();}
    ...
    public T fieldN(Object value) { this.fieldN = value; return self();}
    protected abstract T self(); // should always return this;
    public abstract AbstractType build();
    }

    private AbstractType(BaseBuilder<?> b) {
        this.field1 = b.field1;
        this.field2 = b.field2;
        ...
        this.fieldN = b.fieldN;
    }
}

et pourquoi protected static ? Parce que je veux qu'un sous-type non abstrait de AbstactType qui implémente son propre constructeur non abstrait et qui est situé à l'extérieur de package X puisse accéder et réutiliser le BaseBuilder .

package Y;
public MyType1 extends AbstractType {
    private Object filedN1;

    public static class Builder extends AbstractType.BaseBuilder<Builder> {
        private Object fieldN1; // = some default value here

        public Builder fieldN1(Object value) { this.fieldN1 = value; return self();}
        @Override protected Builder self() { return this; }
        @Override public MyType build() { return new MyType(this); }
    }

    private MyType(Builder b) {
        super(b);
        this.fieldN1 = b.fieldN1;
    }
}

bien sûr que nous pouvons rendre le BaseBuilder public mais alors nous arrivons à une autre déclarations contradictoires:

  • Nous avons un non-instantiatable classe (abstraite)
  • nous fournissons un constructeur public pour elle

donc dans les deux cas avec protected static et public constructeur d'un abstract class nous combinons des affirmations contradictoires. C'est une question de préférences personnelles.

Cependant, je préfère encore le public constructeur d'une abstract class parce que le protected static me semble plus contre-nature dans un monde OOD et OOP !

0
répondu egelev 2018-09-06 08:29:40