Java >> Java tutorial >  >> Tag >> protected

Hvorfor vi ikke skal bruge beskyttet statisk i java

Det er mere en stilistisk ting end et direkte problem. Det tyder på, at du ikke har tænkt ordentligt igennem, hvad der foregår i klassen.

Tænk over hvad static betyder:

Denne variabel findes på klasseniveau, den eksisterer ikke separat for hver forekomst og den eksisterer ikke uafhængigt i klasser, der udvider mig .

Tænk over hvad protected betyder:

Denne variabel kan ses af denne klasse, klasser i samme pakke og klasser som udvider mig .

De to betydninger udelukker ikke ligefrem hinanden, men det er ret tæt på.

Det eneste tilfælde, jeg kan se, hvor du kan bruge de to sammen, er, hvis du havde en abstrakt klasse, der var designet til at blive udvidet, og den udvidende klasse kunne derefter ændre adfærden ved hjælp af konstanter defineret i originalen. Den slags arrangementer ville dog højst sandsynligt ende meget rodet og indikerer svaghed i klassernes design.

I de fleste tilfælde ville det være bedre at have konstanterne som offentlige, da det bare gør alting renere og giver underklasserne mere fleksibilitet. Helt bortset fra alt andet er komposition i mange tilfælde at foretrække frem for arv, mens abstrakte klasser tvinger nedarvning.

For at se et eksempel på, hvordan dette kunne bryde ting og for at illustrere, hvad jeg mener med, at variablen ikke har en uafhængig eksistens, prøv denne eksempelkode:

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

Du vil se resultaterne:

test
changed

Prøv det selv på:https://ideone.com/KM8u8O

Klassen Test2 er i stand til at få adgang til det statiske medlem test fra Test uden at skulle kvalificere navnet - men det arver eller får ikke sin egen kopi. Den ser på nøjagtig det samme objekt i hukommelsen.


Det er ilde set, fordi det er selvmodsigende.

Lav en variabel protected antyder, at den vil blive brugt i pakken eller det vil blive nedarvet inden for en underklasse .

Gør variablen static gør det til et medlem af klassen, eliminerer intentionerne om at arve det . Dette efterlader kun intentionen om at blive brugt inden for en pakke , og vi har package-private for det (ingen modifikator).

Den eneste situation, jeg kunne finde dette nyttigt til, er, hvis du erklærede en klasse, der skulle bruges til at starte applikationen (som JavaFX's Application#launch , og ønskede kun at kunne starte fra en underklasse. Hvis du gør det, skal du sikre dig, at metoden også er final at forbyde at gemme sig. Men dette er ikke "normen", og det blev sandsynligvis implementeret for at forhindre tilføjelse af mere kompleksitet ved at tilføje en ny måde at starte applikationer på.

For at se adgangsniveauerne for hver modifikator, se dette:Java-tutorials - Kontrol af adgang til medlemmer af en klasse


Jeg kan ikke se en særlig grund til, at dette skal være ilde set. Der kan altid være alternativer til at opnå den samme adfærd, og det vil afhænge af den faktiske arkitektur, om disse alternativer er "bedre" end en beskyttet statisk metode eller ej. Men et eksempel, hvor en beskyttet statisk metode i det mindste ville være rimelig, kunne være følgende:

(Redigeret til at opdele i separate pakker, for at gøre brug af protected klarere)

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

Afledt af det:

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

En anden afledt klasse:

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

protected static modifikator kan helt sikkert begrundes her:

  • Metoderne kan være static , fordi de ikke afhænger af instansvariabler. De er ikke beregnet til at blive brugt direkte som en polymorf metode, men er snarere "utility" metoder, der tilbyder standard implementeringer som er en del af en mere kompleks beregning og fungerer som "byggesten" i den faktiske implementering.
  • Metoderne bør ikke være public , fordi de er en implementeringsdetalje. Og de kan ikke være private fordi de skulle kaldes af de udvidende klasser. De kan heller ikke have "standard" synlighed, for så vil de ikke være tilgængelige for de udvidende klasser i andre pakker.

(EDIT:Man kunne antage, at den oprindelige kommentar kun refererede til felter , og ikke til metoder - så var det dog for generelt)


Java tag