OBJEKTINIS PROGRAMAVIMAS

Java prieigos modifikatoriai

Prieigos modifikatoriai (angl. access modifiers) nustato, iš kurių programos vietų galima naudoti klasę, atributą, metodą ar konstruktorių. Jie padeda apsaugoti vidinę objekto būseną ir aiškiai apibrėžti viešą klasės sąsają.

Dvi modifikatorių grupės

  • Prieigos modifikatoriai valdo, kur kodas yra pasiekiamas: public, private ir protected.
  • Kiti modifikatoriai suteikia kitą elgseną, pavyzdžiui, , final arba abstract.

Šioje pamokoje nagrinėjami būtent prieigos lygiai.

Aukščiausio lygio klasių prieiga

Aukščiausio lygio klasei galima suteikti public arba paketo prieigą, nenurodant modifikatoriaus:

Java aukščiausio lygio klasių prieiga
PrieigaPasiekiamumas
publicIš bet kurio paketo, jei klasė tinkamai importuota
Paketo prieigaTik iš to paties paketo; modifikatorius nerašomas
// Failas: Knyga.java
public class Knyga {
    // Klasė pasiekiama ir iš kitų paketų
}

// Modifikatorius nenurodytas – paketo prieiga
class KnygosPagalbininkas {
    // Klasė pasiekiama tik tame pačiame pakete
}
Konsolės rezultato nėra.

Čia tik parodomos dvi klasių deklaracijos. Nė viena klasė neturi main() ar println().

  1. public class Knyga gali būti naudojama ir iš kitų paketų.
  2. Viešos klasės failo vardas turi sutapti su klasės vardu: Knyga.java.
  3. Prie KnygosPagalbininkas neparašytas joks prieigos modifikatorius.
  4. Todėl ši klasė turi paketo prieigą ir ją gali naudoti tik to paties paketo kodas.
default nėra čia rašomas raktažodis.

Sąvoka „numatytoji prieiga“ reiškia, kad prieigos modifikatorius tiesiog nenurodytas.

Atributų, metodų ir konstruktorių prieiga

Java klasės narių prieigos lygiai
ModifikatoriusTa pati klasėTas pats paketasPoklasis kitame paketeKitos klasės kitame pakete
private✅ Taip❌ Ne❌ Ne❌ Ne
(numatytoji)✅ Taip✅ Taip❌ Ne❌ Ne
protected✅ Taip✅ Taip✅ Taip*❌ Ne
public✅ Taip✅ Taip✅ Taip✅ Taip
* protected prieiga kitame pakete turi papildomą taisyklę.

Poklasis narį pasiekia per paveldėjimą – per save arba savo poklasio objektą. Jis negali naudoti protected nario per bet kokį atskirai gautą tėvinės klasės objektą.

public ir private pavyzdys

Viešas knygos pavadinimas pasiekiamas iš išorės, tačiau perskaitytų puslapių skaičius saugomas klasės viduje. Išorinis kodas reikšmę gauna per viešą metodą:

class Knyga {
    public String pavadinimas = "Mažasis princas";
    private int perskaitytaPuslapiu = 40;

    public int gautiPerskaitytusPuslapius() {
        return perskaitytaPuslapiu;
    }
}

public class Main {
    public static void main(String[] args) {
        Knyga knyga = new Knyga();

        System.out.println(knyga.pavadinimas);
        System.out.println(knyga.gautiPerskaitytusPuslapius());
    }
}
Konsolės rezultatas

Mažasis princas
40

  1. Atributas pavadinimas pažymėtas public, todėl Main jį pasiekia tiesiogiai.
  2. Atributas perskaitytaPuslapiu pažymėtas private, todėl iš išorės jo tiesiogiai pasiekti negalima.
  3. Viešas metodas gautiPerskaitytusPuslapius() veikia pačios klasės viduje ir gali perskaityti privatų atributą.
  4. Main iškviečia šį metodą ir saugiai gauna skaičių 40.

Tiesioginis privataus atributo naudojimas atrodytų taip:

Knyga knyga = new Knyga();

System.out.println(knyga.perskaitytaPuslapiu);
Kompiliatoriaus rezultatas

error: perskaitytaPuslapiu has private access in Knyga

  1. Kodas bando pasiekti knyga.perskaitytaPuslapiu ne iš pačios Knyga klasės.
  2. Modifikatorius private leidžia lauką naudoti tik klasės viduje.
  3. Kompiliatorius sustabdo programą, todėl šis klaidingas fragmentas konsolės išvesties neturi.
  4. Teisingas kelias yra naudoti klasės suteiktą viešą metodą.

Paketo prieiga

Kai modifikatorius nenurodytas, klasės narys pasiekiamas tik tame pačiame pakete. Tai naudinga vidinėms vieno modulio detalėms, kurių nereikia atverti visai programai.

package lt.pavyzdys.knygos;

class KnygosPagalbininkas {
    int puslapiuSkaicius = 96;

    void rodytiPuslapius() {
        System.out.println("Puslapių: " + puslapiuSkaicius);
    }
}

public class Main {
    public static void main(String[] args) {
        KnygosPagalbininkas pagalbininkas = new KnygosPagalbininkas();
        pagalbininkas.rodytiPuslapius();
    }
}
Konsolės rezultatas

Puslapių: 96

  1. Abi klasės priklauso tam pačiam paketui lt.pavyzdys.knygos.
  2. Prie KnygosPagalbininkas, jo atributo ir metodo neparašytas modifikatorius.
  3. Tai reiškia, kad visi jie pasiekiami tame pačiame pakete.
  4. Main sukuria pagalbininko objektą ir iškviečia jo metodą.
  5. Jeigu Main būtų kitame pakete, toks naudojimas nebūtų leidžiamas.

Ką iš tikrųjų leidžia protected?

protected lengviausia suprasti kaip dviejų leidimų derinį. Narį gali naudoti bet kuri klasė tame pačiame pakete. Be to, jį per paveldėjimą gali naudoti poklasis, net jei poklasis yra kitame pakete.

Pagrindinė mintis

protected nėra „pasiekiamas visur“. Kitame pakete jis suteikia papildomą prieigą būtent poklasiui ir būtent per paveldėjimą.

Toliau klasės sąmoningai įdėtos į du skirtingus paketus. Jei jos būtų tame pačiame pakete, pavyzdys neparodytų svarbiausio protected skirtumo:

// Failas: biblioteka/Leidinys.java
package biblioteka;

public class Leidinys {
    protected String pavadinimas = "Mažasis princas";

    protected void rodytiPavadinima() {
        System.out.println(pavadinimas);
    }
}

// Failas: parduotuve/Knyga.java
package parduotuve;

import biblioteka.Leidinys;

public class Knyga extends Leidinys {
    public void rodytiInformacija() {
        // Leidžiama, nes Knyga paveldi iš Leidinys
        this.rodytiPavadinima();
        System.out.println(this.pavadinimas);
        System.out.println("Tai yra knyga");
    }

    public static void main(String[] args) {
        Knyga knyga = new Knyga();
        knyga.rodytiInformacija();

        // Negalima: kitame pakete protected narys
        // nepasiekiamas per paprastą Leidinys objektą.
        // Leidinys leidinys = new Leidinys();
        // leidinys.rodytiPavadinima();
    }
}
Konsolės rezultatas

Mažasis princas
Mažasis princas
Tai yra knyga

  1. Leidinys yra pakete biblioteka. Jis turi protected atributą pavadinimas ir metodą rodytiPavadinima().
  2. Knyga yra kitame pakete – parduotuve. Vadinasi, vien buvimo tame pačiame pakete taisyklė jai nepadeda.
  3. Knyga extends Leidinys padaro Knyga klasę Leidinys poklasiu.
  4. Dėl paveldėjimo Knyga viduje galima rašyti this.rodytiPavadinima() ir this.pavadinimas.
  5. Pirmoji eilutė atsiranda iš paveldėto metodo, antroji – tiesiogiai perskaičius paveldėtą atributą, trečioji – iš pačios Knyga klasės.
  6. Tačiau Knyga negali sukurti paprasto Leidinys objekto ir per jį pasiekti protected metodo. Komentaruose parodytos eilutės būtų kompiliavimo klaida.
Kaip nario modifikatorius pakeistų šį pavyzdį?
ModifikatoriusAr Knyga kitame pakete galėtų narį naudoti?Kodėl?
private❌ NeNarys tiesiogiai pasiekiamas tik pačioje Leidinys klasėje.
Numatytoji prieiga❌ NeKnyga yra kitame pakete.
protected✅ Taip, per paveldėjimąKnyga yra Leidinys poklasis.
public✅ TaipViešas narys pasiekiamas ir be specialios poklasio išimties.
Trumpa taisyklė atminčiai

private – tik klasė; numatytoji prieiga – paketas; protected – paketas ir poklasiai; public – visur.

Konstruktoriaus prieigos ribojimas

Prieigos modifikatorius gali valdyti ir tai, kas gali kurti klasės objektus:

public class BibliotekosInformacija {
    private BibliotekosInformacija() {
        // Objektų iš išorės kurti negalima
    }

    public static void rodytiPavadinima() {
        System.out.println("Miesto biblioteka");
    }

    public static void main(String[] args) {
        BibliotekosInformacija.rodytiPavadinima();
    }
}
Konsolės rezultatas

Miesto biblioteka

  1. Klasės konstruktorius pažymėtas private, todėl kitos klasės negali rašyti new BibliotekosInformacija().
  2. Tačiau viešas static metodas priklauso pačiai klasei ir objektui jo nereikia.
  3. Metodas iškviečiamas per klasės pavadinimą BibliotekosInformacija.rodytiPavadinima().
  4. Toks sprendimas tinka pagalbinėms klasėms, kurios teikia tik statinius veiksmus arba pačios kontroliuoja objektų kūrimą.

Kokį prieigos lygį rinktis?

  • Pradėk nuo siauriausios reikalingos prieigos.
  • Objekto vidinius atributus dažniausiai žymėk private.
  • public palik sąmoningai kuriamai klasės sąsajai.
  • protected naudok tik kai paveldinčios klasės iš tikrųjų turi pasiekti narį.
  • Paketo prieiga tinka susijusių to paties paketo klasių vidiniam bendradarbiavimui.