Pourquoi ne pas utiliser protected static en java


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

Si jamais vous voyez un protected static, courir.

Quelqu'un Peut-il expliquer pourquoi un protected static mal vu?

Author: Community, 2014-06-18

8 answers

C'est plus une chose stylistique qu'un problème direct. Cela suggère que vous n'avez pas correctement 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 instance et elle n'a pas d'existence indépendante dans les classes qui m'étendent.

Pensez à ce que protected signifie:

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

Les deux significations ne sont pas exactement mutuellement exclusives 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çue pour être étendue et que la classe d'extension pouvait ensuite modifier le comportement en utilisant des constantes définies dans l'original. Même alors c'est une raison très faible cependant comme vous le feriez presque certainement mieux d'avoir les constantes comme public. Cela rend tout plus propre et permet aux personnes de sous-classer plus de flexibilité.

Pour développer et expliquer le premier point-essayez cet exemple de code:

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 à: https://ideone.com/KM8u8O

La classe Test2 peut accéder au membre statique test à partir de Test sans avoir besoin de qualifier le nom - mais elle n'hérite pas ou n'obtient pas sa propre copie. Il regarde exactement la même chose variable.

 66
Author: Tim B, 2015-11-13 22:49:31

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

Faire une variable protected implique qu'il sera utilisé dans le package, ou il sera héritées dans une sous-classe.

Rendre la variable static en fait un membre de la classe, éliminant les intentions de l'hériter . 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 JavaFX Application#launch, et que vous vouliez seulement pouvoir lancer à partir d'une sous-classe. Dans ce cas, assurez - vous que la méthode est également final pour interdire masquant. Mais ce n'est pas "la norme", et a probablement été implémenté pour éviter d'ajouter plus de complexité en ajoutant une nouvelle façon de lancer des applications.

Pour voir les niveaux d'accès de chaque modificateur, voir ceci: Les tutoriels Java-Contrôle de l'accès aux membres d'un Classe

 26
Author: Vince Emigh, 2016-08-04 17:04:28

Je ne vois pas de raison particulière pour laquelle cela devrait être mal vu. Il peut toujours y avoir des alternatives pour obtenir le même comportement, et cela dépendra de l'achitecture 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:

(Édité pour diviser 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 que:

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

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

  • Les méthodes peuvent être static, car 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 "utilitaires" qui offrent des implémentations par défaut qui font partie d'un calcul plus complexe et servent de "blocs de construction" de l'implémentation réelle.
  • Les méthodes devraient ne pas être public, car ils sont un détail d'implémentation. Et ils ne peuvent pas être private car ils devraient être appelés par les classes d'extension. Ils ne peuvent pas non plus avoir de visibilité "par défaut", car ils ne seront pas accessibles pour les classes d'extension dans d'autres packages.

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

 11
Author: Marco13, 2014-06-18 15:40:43

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 la classe contenant), donc un protected static a la même visibilité que static, suggérant un malentendu par le codeur.

 7
Author: Bohemian, 2014-06-18 15:21:33

Protected est utilisé afin qu'il puisse être utilisé dans les sous-classes. Il n'y a pas de logique dans la définition d'une statique protégée lors de l'utilisation dans le contexte de classes concrètes car vous pouvez accéder à la même variable de manière statique.Cependant, le complier donnera un avertissement pour accéder à la variable statique de super classe de manière statique.

 3
Author: 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 ou une méthode statique visible pour le package et toutes les sous-classes de la classe déclarante, allez-y et faites-la protected static.

Certaines personnes évitent généralement d'utiliser protected pour diverses raisons et certaines personnes pensent que les variables non finales static doivent être évitées par tous les moyens (je sympathise personnellement avec ce dernier dans une certaine mesure), donc je suppose que la combinaison de protected et static doit regarder mauvais^2 pour ceux qui appartiennent aux deux groupes.

 3
Author: x4u, 2014-06-18 22:44:52

Il n'y a rien de mal à avoir protected static. Une chose que beaucoup de gens négligent est que vous voudrez peut-être é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
Author: Aelphaeis, 2016-07-05 15:34:02

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

  • protected signifie - ' package-private + visibility to subclasses - la propriété / comportement est HÉRITÉE '
  • static signifie - ' le contraire de l'instance-c'est une propriété/comportement de CLASSE, c'est-à-dire qu'il n'est PAS HÉRITÉ '

Par conséquent, ils sont légèrement contradictoires et incompatibles.

Cependant, récemment, je suis arrivé à un cas d'utilisation où il pourrait être logique d'utiliser ces deux ensemble. Imaginez que vous voulez créer un abstract la classe qui est un parent de immuable types 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 peut 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 un sous-type non abstrait de {[6] } qui implémente son propre constructeur non abstrait et est situé en dehors de {[7] } pour pouvoir 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, nous pouvons rendre le BaseBuilder public, mais ensuite nous arrivons à une autre déclaration contradictoire:

  • Nous avons une classe non instanciable (abstract)
  • Nous fournissons un constructeur public pour elle

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

Cependant, je préfère toujours le public constructeur de un abstract class parce que le protected static pour moi se sent plus contre nature dans un monde OOD et OOP !

 0
Author: egelev, 2018-09-06 08:29:40