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?
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.
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
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 êtreprivate
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)
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.
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.
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.
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é.
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 !