IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

10. diel - Gettery a settery v Jave

V predchádzajúcom cvičení, Riešené úlohy k 9. lekcii OOP v Jave, sme si precvičili získané skúsenosti z predchádzajúcich lekcií.

Dnes sa v tutoriáli pozrieme na tzv. gettery a settery.

Gettery a settery

Veľmi často sa nám stáva, že chceme mať kontrolu nad zmenami nejakého atribútu objektu zvonku. Budeme chcieť atribút nastaviť ako read-only (len na čítanie) alebo reagovať na jeho zmeny. Založme si nový projekt s názvom napr. GetSet a vytvorme nasledujúcu triedu Student, ktorá bude reprezentovať študenta v nejakom informačnom systéme:

class Student {
    public String name;
    public boolean male;
    public int age;
    public boolean fullAged;

    public Student(String name, boolean male, int age) {
        this.name = name;
        this.male = male;
        this.age = age;
        fullAged = true;
        if (age < 18) {
            fullAged = false;
        }
    }

    @Override
    public String toString() {
        String iAmFullAged = "I'm";
        if (!fullAged) {
            iAmFullAged = "I'm not";
        }
        String gender = "male";
        if (!male) {
            gender = "female";
        }
        return String.format("I'm %s, %s. I'm %d years old and %s of age.", name, gender, age, iAmFullAged);
    }
}

Trieda je veľmi jednoduchá, študent sa nejako volá, je nejakého pohlavia a má určitý vek. Podľa tohto veku sa nastavuje atribút fullAged pre pohodlnejšie vyhodnocovanie plnoletosti na rôznych miestach systému. Na uloženie pohlavia používame hodnotu typu boolean, či je študent muž. Konštruktor podľa veku určí, či je študent plnoletý. Metóda toString() je navrhnutá pre potreby tutoriálu tak, aby nám vypísala všetky informácie. V reáli by vrátila pravdepodobne len meno študenta. Pomocou konštruktora si nejakého študenta vytvorme:

        Student student = new Student("Peter Brown", true, 20);
        System.out.println(student);

Výstup:

Konzolová aplikácia
I'm Peter Brown, male. I'm 20 years old and I'm of age.

Všetko vyzerá pekne, ale atribúty sú prístupné ako na čítanie, tak na zápis. Objekt teda môžeme rozbiť napríklad takto (hovoríme o nekonzistentnom vnútornom stave):

        Student student = new Student("Peter Brown", true, 20);
        student.age = 15;
        student.male = true;
        System.out.println(student);

Výstup:

Konzolová aplikácia
I'm Peter Brown, male. I'm 15 years old and I'm of age.

Určite musíme ošetriť, aby sa plnoletosť obnovila pri zmene veku. Keď sa zamyslíme nad ostatnými atribútmi, nie je najmenší dôvod, aby sme taktiež umožňovali modifikovať pohlavie. Bolo by však zároveň vhodné ich vystaviť na čítanie, nemôžeme ich teda iba nastaviť ako private. V skorších dieloch seriálu sme na tento účel používali metódy, ktoré slúžili na čítanie privátnych atribútov. Ich názov sme volili ako getAge() a pre nastavenie atribútu napríklad setAge(). V Jave sa všetky atribúty, s ktorými sa má pracovať zvonku, označujú ako privátne a pre prístup k nim sa definujú práve podobné metódy. Na ich pomenovanie sa ustálilo getFieldName() na čítanie a setFieldName() na zápis. Ak je atribút typu boolean, volá sa getter isFieldName(). Trieda by novo vyzerala napr. takto:

class Student {
    private String name;
    private boolean male;
    private int age;
    private  boolean fullAged;

    public Student(String name, boolean male, int age) {
        this.name = name;
        this.male = male;
        setAge(age);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isMale() {
        return male;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
        // updating whether student is of age
        fullAged = age >= 18;
    }


    public boolean isFullAged() {
        return fullAged;
    }

    @Override
    public String toString() {
        String iAmFullAged = "I'm";
        if (!fullAged) {
            iAmFullAged = "I'm not";
        }
        String gender = "male";
        if (!male) {
            gender = "female";
        }
        return String.format("I'm %s, %s. I'm %d years old and %s of age.", name, gender, age, iAmFullAged);
    }
}

Metódy, čo hodnoty iba vracajú, sú veľmi jednoduché. Nastavenie veku má už nejakú vnútornú logiku, pri jeho zmene musíme totiž prehodnotiť atribút fullAged. Zaistili sme, že sa do premenných nedá zapisovať inak, než my chceme. Máme teda pod kontrolou všetky zmeny atribútov a dokážeme na ne reagovať. Nemôže sa stať, že by nám niekto vnútorný stav nekontrolovane menil a rozbil. Všimnite si aj zmeny v konštruktore, kde sa nastavuje vek metódou setAge().

Metódam na vrátenie hodnoty sa hovorí gettery a metódam pre zápis settery. Pre editáciu ostatných atribútov by sme urobili jednu metódu editStudent(), ktorá by bola podobná konštruktoru.

Otázkou je, aká je teraz výhoda toho, že je atribút name privátne, keď do neho ide zapisovať a možno z neho aj čítať. Veď máme v kóde zbytočne 2 metódy, ktoré tam zaberajú miesto a ešte je to pomalé?

Naozaj sme to napísali správne, alebo aspoň tak, ako sa to bežne robí. Java pred kompiláciou vykonáva početné optimalizácie a pokiaľ sú metódy tak jednoduché, že iba vracajú hodnotu alebo ju nastavujú, metóda sa skompiluje ako priamy prístup do pamäte. Sú teda rovnako rýchle, ako keby sme pracovali s verejným atribútom (za predpokladu, že setter alebo getter nemá nejakú ďalšiu logiku).

IDE dokáže gettery a settery automaticky generovať, nemusíme ich teda otrocky opisovať. Stačí na privátnu premennú kliknúť pravým tlačidlom a zvoliť položku Refactor -> Encapsulate fields:

Automatické generovanie getterov a setterov v IntelliJ - Objektovo orientované programovanie v Jave

V ďalšom dialógu si zaškrtneme, ku ktorým atribútom chceme vygenerovať gettery a settery. My nebudeme chcieť sprístupniť pre zápis atribúty fullAged a male. Atribút fullAged pôjde zmeniť iba zmenením veku študenta. Pohlavie nedáva zmysel meniť vôbec (pokiaľ by to bolo naozaj niekedy potrebné, bola by na to nejaká špeciálna metóda, aby sa vylúčila zmena chybou v kóde). Dialóg potvrdíme:

Automatické generovanie getterov a setterov v IntelliJ - Objektovo orientované programovanie v Jave

Settery pre atribúty fullAged a male z triedy teda odstránime.

Optimalizácia pred kompiláciou odstránila rýchlostný problém, ktorý by inak zbytočné volanie metód spôsobovalo. Aj zbytočné písanie metód sme vykompenzovali ich automatickým generovaním. Otázkou zostáva, v čom je písanie metód oproti atribútom výhodnejšie.

Hlavným dôvodom je určitá štandardizácia. Nemusíme premýšľať nad tým, či je daná vlastnosť objektu riešená cez getter alebo atribút, na inštanciu jednoducho vždy voláme metódu začínajúcu slovom get (prípadne is) pokiaľ chceme vlastnosť inštancie čítať, prípadne metódu začínajúcu set, ak ju chceme zmeniť.

Ďalšou výhodou je, že keď sa v budúcnosti rozhodneme, že nejaký atribút chceme urobiť read-only (len na čítanie), jednoducho zmažeme setter. Nemusíme vytvárať getter a meniť viditeľnosť atribútu, čo by zmenilo rozhranie triedy a rozbilo existujúci kód, ktorý by ju používal.

Gettery a settery teda budeme odteraz používať pri všetkých atribútoch, ktoré majú byť zvonku prístupné. V našich triedach sa takmer nebudú vyskytovať atribúty s viditeľnosťou public.

Skúsme si teraz ešte spustiť kód, ktorý predtým rozbil interný stav objektu:

        Student student = new Student("Peter Brown", true, 20);
        student.setAge(15);
        // s.setMale(false); // This line has to be commented out since it's no longer possible to change the gender
        System.out.println(student);

Výstup je už v poriadku:

Konzolová aplikácia
I'm Peter Brown, male. I'm 15 years old and I'm not of age.

V nasledujúcom kvíze, Kvíz - Dedičnosť, statika, gettery a settery v Jave OOP, si vyskúšame nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 10x (2.8 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java

 

Predchádzajúci článok
Riešené úlohy k 9. lekcii OOP v Jave
Všetky články v sekcii
Objektovo orientované programovanie v Jave
Preskočiť článok
(neodporúčame)
Kvíz - Dedičnosť, statika, gettery a settery v Jave OOP
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
22 hlasov
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity