Oslav s námi vysvědčení a získej 90 % extra kreditů ZDARMA při nákupu od 1199 kreditů. Použij promo kód VYSVEDCENI90 pouze dnes!
NOVINKA: Získej 40 hodin praktických dovedností s AI – ZDARMA ke každému akreditovanému kurzu!

Lekce 4 - Hrací kostka v Javě - Zapouzdření a konstruktor

V předešlém cvičení, Řešené úlohy k 3. lekci OOP v Javě, jsme si procvičili nabyté zkušenosti z předchozích lekcí.

V dnešním tutoriálu začneme pracovat na slíbené aréně, ve které budou proti sobě bojovat dva bojovníci. Boj bude tahový (na přeskáčku) a bojovník vždy druhému ubere život na základě síly jeho útoku a obrany druhého bojovníka. Simulujeme v podstatě stolní hru, budeme tedy simulovat i hrací kostku, která dodá hře prvek náhodnosti. Začněme zvolna a vytvořme si dnes právě tuto hrací kostku. Zároveň se naučíme jak definovat vlastní konstruktor.

Základní pilíře OOP

OOP stojí na základních třech pilířích:

  • Zapouzdření
  • Dědičnost
  • Polymorfismus

Dnes použijeme první z nich.

Vytvoření projektu

Vytvořme si nový projekt a pojmenujme ho TahovyBoj. K projektu si přidejme novou třídu s názvem Kostka. Zamysleme se nad atributy, které kostce dáme. Jistě by se hodilo, kdybychom si mohli zvolit počet stěn kostky (klasicky 6 nebo 10 stěn, jak je zvykem u tohoto typu her). Naše třída proto bude mít atribut pocetSten. Třídu Kostka upravíme do následující podoby:

/**
 * Třída reprezentuje hrací kostku.
 */
public class Kostka {
     /**
      * Počet stěn kostky
      */
     public int pocetSten;

}

Konstruktory

Konstruktor je speciální metoda, která se sama zavolá ve chvíli vytvoření instance objektu. Slouží k nastavení vnitřního stavu objektu a k provedení případné inicializace. Přejdeme do souboru TahovyBoj.java, kde kostku vytvoříme tímto způsobem:

Kostka kostka = new Kostka();

Právě Kostka() je konstruktor. Protože v naší třídě žádný není, Java si sama vygeneruje prázdný konstruktor. My si však nyní konstruktor do třídy přidáme. Deklaruje se jako metoda, ale nemá návratový typ a musí mít stejný název jako je název třídy (začíná tedy, na rozdíl od ostatních metod, velkým písmenem), v našem případě tedy Kostka. V konstruktoru nastavíme počet stěn na pevnou hodnotu.

Přejdeme do souboru Kostka.java a přidáme do třídy metodu Kostka(). V ní nastavíme hodnotu atributu pocetSten:

/**
 * Třída reprezentuje hrací kostku.
 */
public class Kostka {
     /**
      * Počet stěn kostky
      */
     public int pocetSten;

     /**
      * Vytvoří novou instanci hrací kostky
      */
     public Kostka() {
         pocetSten = 6;
     }
}

Přesuňme se do souboru TahovyBoj.java a vyzkoušejme si vytvořit kostku a vypsat počet stěn:

        Kostka kostka = new Kostka(); // v tuto chvíli se zavolá konstruktor
        System.out.println(kostka.pocetSten);

V konzoli vidíme výstup:

Atribut pocetSten:
6

Vidíme, že se konstruktor opravdu zavolal.

Volitelný počet stěn

My bychom ale chtěli, abychom mohli u každé kostky při vytvoření specifikovat, kolik stěn budeme potřebovat. Přejdeme do souboru Kostka.java a dáme tedy konstruktoru parametr:

public Kostka(int novyPocetSten) {
       pocetSten = novyPocetSten;
}

Všimněte si, že jsme před název parametru metody přidali slovo novy, protože jinak by měl stejný název jako atribut a Javu by to zmátlo. Vraťme se do souboru TahovyBoj.java a zadejme tento parametr do konstruktoru:

        Kostka kostka = new Kostka(10); // v tuto chvíli se zavolá konstruktor s par. 10
        System.out.println(kostka.pocetSten);

V konzoli vidíme výstup:

Výstup s parametrem konstruktoru 10:
10

Vše funguje, jak jsme očekávali.

Výchozí hodnota kostky

Java nám již v tuto chvíli nevygeneruje prázdný (tzv. bezparametrický) konstruktor, takže kostku bez parametru již vytvořit nelze. My to však můžeme umožnit, vytvořme si další konstruktor a tentokrát bez parametru. V něm nastavíme počet stěn na 6, protože takovou hodnotu asi uživatel naší třídy u kostky očekává jako výchozí. Přejdeme tedy zpátky do souboru Kostka.java a vytvoříme konstruktor bez parametru:

public Kostka() {
    pocetSten = 6;
}

Třída Kostka má tedy nyní dva konstruktory.

Zkusme si nyní vytvořit 2 instance kostky, každou jiným konstruktorem v souboru TahovyBoj.java:

        Kostka sestistenna = new Kostka();
        Kostka desetistenna = new Kostka(10);
        System.out.println(sestistenna.pocetSten);
        System.out.println(desetistenna.pocetSten);

Výstup:

Konzolová aplikace
6
10

Javě nevadí, že máme dvě metody se stejným názvem, protože jejich parametry jsou různé. Hovoříme o tom, že metoda Kostka() (tedy zde konstruktor) má přetížení (overload). Toho můžeme využívat i u všech dalších metod, nejen u konstruktorů. IDE nám přehledně nabízí všechny přetížení metody ve chvíli, kdy zadáme její název. V nabídce vidíme naše 2 konstruktory:

Nabídka s konstruktory - Objektově orientované programování v Javě

Mnoho metod v Javě má hned několik přetížení, zkuste se podívat např. na metodu indexOf() na třídě String. Je dobré si u metod projít jejich přetížení, abyste neprogramovali něco, co již někdo udělal před vámi.

Ukážeme si ještě, jak jde obejít nepraktický název atributu u parametrického konstruktoru (v našem případě novyPocetSten) a potom konstruktory opustíme. Problém je samozřejmě v tom, že když napíšeme:

public Kostka(int pocetSten) {
    pocetSten = pocetSten;
}

Java neví, kterou z proměnných myslíme, jestli parametr nebo atribut. V tomto případě přiřazujeme do parametru znovu ten samý parametr. IDE nás na tuto skutečnost dokonce upozorní. Uvnitř třídy se máme možnost odkazovat na její instanci, je uložena v proměnné this. Využití si můžeme představit např. kdyby kostka měla metodu dejHraci(Hrac hrac) a tam by volala hrac.seberKostku(this). Zde bychom hráči pomocí referenční proměnné this předali sebe sama, tedy tu konkrétní kostku, se kterou pracujeme. My se tím zde nebudeme zatěžovat, ale využijeme odkazu na instanci při nastavování atributu:

public Kostka(int pocetSten) {
    this.pocetSten = pocetSten;
}

Pomocí proměnné this jsme specifikovali, že levá proměnná pocetSten náleží instanci, pravou Java chápe jako z parametru. Máme tedy dva konstruktory, které nám umožňují tvořit různé hrací kostky. Přejděme dál.

Zapouzdření

Zapouzdření umožňuje skrýt některé metody a atributy tak, aby zůstaly použitelné jen pro třídu zevnitř. Objekt si můžeme představit jako černou skřínku (anglicky blackbox), která má určité rozhraní (interface), přes které jí předáváme instrukce/data a ona je zpracovává.

Nevíme, jak to uvnitř funguje, ale víme, jak se navenek chová a používá. Nemůžeme tedy způsobit nějakou chybu, protože využíváme a vidíme jen to, co tvůrce třídy zpřístupnil.

Příkladem může být třída Clovek, která bude mít atribut datumNarozeni a na jeho základě další atributy jako plnolety a vek. Kdyby někdo objektu zvenčí změnil datumNarozeni, přestaly by platit proměnné plnolety a vek. Říkáme, že vnitřní stav objektu by byl nekonzistentní. Toto se nám ve strukturovaném programování může klidně stát. V OOP však objekt zapouzdříme. Atribut datumNarozeni označíme jako privátní a tím pádem bude jasné, že nechceme, aby nám jej někdo jen tak měnil. Naopak ven vystavíme metodu zmenDatumNarozeni(), která dosadí nové datum narození do proměnné datumNarozeni a zároveň provede potřebný přepočet věku a přehodnocení plnoletosti. Použití objektu je bezpečné a aplikace stabilní.

Zapouzdření tedy tlačí programátory používat objekt jen tím správným způsobem. Rozhraní (interface) třídy rozdělí na veřejně přístupné (public) a vnitřní strukturu (private).

Zapouzdření atributu pocetSten

Minule jsme kvůli jednoduchosti nastavovali všechny atributy naší třídy jako public, tedy jako veřejně přístupné. Většinou se však spíše nechce, aby se daly zvenčí modifikovat a používá se modifikátor private. Atribut je poté viditelný jen uvnitř třídy a zvenčí se Java tváří, že vůbec neexistuje. Při návrhu třídy tedy nastavíme vše na private a v případě, že něco bude opravdu potřeba vystavit, použijeme modifikátor public. Naše třída nyní vypadá takto:

/**
 * Vytvoří novou instanci hrací kostky
 */
public class Kostka {
     /**
      * Počet stěn kostky
      */
     private int pocetSten;

Nyní nám nebude moci nikdo u již vytvořené kostky měnit počet stěn. Umožníme však počet stěn zvenku přečíst. V souboru Kostka.java přidáme do třídy metodu vratPocetSten(), která nám vrátí hodnotu atributu pocetSten. Docílili jsme tím v podstatě toho, že je atribut read-only (atribut není viditelný a lze ho pouze číst metodou, změnit ho nelze). Nová metoda bude vypadat asi takto:

/**
 * Vrátí počet stěn hrací kostky
 * @return Počet stěn hrací kostky
 */
public int vratPocetSten() {
    return pocetSten;
}

Přesuňme se do souboru TahovyBoj.java a upravme výpis počtu stěn na použití nové metody:

        Kostka sestistenna = new Kostka();
        Kostka desetistenna = new Kostka(10);
        System.out.println(sestistenna.vratPocetSten());
        System.out.println(desetistenna.vratPocetSten());

Po spuštění programu v konzoli vidíme výstup:

Výstup metody vratPocetSten():
6
10

V příští lekci, Hrací kostka v Javě podruhé - Překrývání metod a random, se naučíme překrývat metody, pracovat s náhodnými čísly a dokončíme hrací kostku.


 

Měl jsi s čímkoli problém? Zdrojový kód vzorové aplikace je ke stažení každých pár lekcí. Zatím pokračuj dál, a pak si svou aplikaci porovnej se vzorem a snadno oprav.

Předchozí článek
Řešené úlohy k 3. lekci OOP v Javě
Všechny články v sekci
Objektově orientované programování v Javě
Přeskočit článek
(nedoporučujeme)
Hrací kostka v Javě podruhé - Překrývání metod a random
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
843 hlasů
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 se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity