FAV-ZCU/KIV PPA1/6. Třídy a instance.md

397 lines
29 KiB
Markdown
Raw Permalink Normal View History

# Třídy a instance (objekty)
- Objektové programování
- Program je dekomponován na objekty (abstrakce objektů z reálného světa), které udržují data a metody, které s daty pracují, pohromadě
### Třída, instance, reference
- Strukturovaný datový typ
- Na rozdíl od základních datových typů, které obsahují pouze jednu hodnotu a nejde je dále členit, třída může obsahovat data ve formě proměnných (atributů) obecně různého typu
- Kromě dat obsahuje metody, které obecně provádějí operace nad těmito daty
- Třída je šablonou pro tvorbu instancí (objektů)
- Název třídy začíná velkým počátečním písmenem, každé další slovo víceslovného názvu začíná velkým písmenem
- U dokumentačního komentáře třídy se uvádí alespoň jedna řádka popisující účel třídy, dále autor třídy a případně verze (s datem poslední úpravy)
### Instance (objekt)
- Je vytvořena podle konkrétní třídy a nese v sobě konkrétní hodnoty atributů (proměnných)
- Od jedné třídy může být vytvořeno více instancí, přičemž každá může mít (a typicky má) jinak nastavené atributy
- Aby bylo možné s atributy a metodami definovanými ve třídě pracovat, je NUTNÉ vytvořit její instanci (neplatí při použití klíčového slova ```static```)
- Tím se vytvoří místo v paměti pro tuto instanci, do kterého se mimo jiné uloží hodnoty jednotlivých atributů
- Rozdíl oproti základním datovým typům, kdy se místo v paměti vytvořilo v okamžiku deklarace proměnné (tj. v okamžiku provedení řádky ```int i;``` se vytvořilo místo v paměti o velikosti 4 byty pro uložení celého čísla)
- Reference
- Abychom mohli pracovat s instancí a jejími atributy a metodami, potřebujeme na ní referenci
- Reference (referenční proměnná) ukazuje na místo v paměti, kde je uložena konkrétní instance
#### Deklarace referenční proměnné a vytvoření instance
- Referenční proměnná se deklaruje stejně jako proměnná základního datového typu, tj. názevTypu názevProměnné;
- ```názevTypu``` je název třídy,
- ```názevProměnné``` je název referenční proměnné
- Pouhou deklarací referenční proměnné ale instance třídy nevznikne
- Po deklaraci (bez inicializace) je referenční proměnná „prázdná“ není vytvořeno místo v paměti pro instanci a sama referenční proměnná tedy na nic neukazuje
- POZOR! Pokud se jedná o lokální proměnnou (tj., proměnnou deklarovanou uvnitř metody), je vhodné inicializovat referenční proměnnou hodnotou null
- Hodnota ```null``` (klíčové slovo) explicitně říká, že reference neodkazuje (zatím) na žádnou instanci
- Pokud tuto inicializaci neprovedete, hodnota lokální referenční proměnné není definována a při pokusu o její čtení dojde k chybě (už při překladu programu)
- Vytvoření instance
- Instance se vytvoří pomocí operátoru new (klíčové slovo) a přiřadí se do připravené referenční proměnné
- ```referenčníProměnná = new Třída();```
- Referenční proměnná musí být stejného typu jako vytvářená instance (tj. ```Třída```)
- Nebo typu předka třídy nebo rozhraní implementovaného třídou (viz předměty KIV/PPA2 a KIV/OOP)
#### Přístup k atributům a metodám instance
- K jednotlivým atributům (proměnným) a metodám instance přistupujeme přes referenční proměnnou, která na instanci ukazuje
- Používá se tečková notace
- ```referenčníProměnná.proměnnáInstance```
- Do proměnných (pokud jsou viditelné) lze zapisovat hodnoty a lze je i číst
- ```referenčníProměnná.metodaInstance()```
- Metody lze volat (pokud jsou viditelné)
#### Práce s referenčními proměnnými a instancemi
- Do referenčních proměnných lze přiřazovat nové instance i jiné referenční proměnné
- Na jednu instanci může ukazovat více referenčních proměnných
- Pokud už nějakou instanci nebudeme používat, můžeme do referenční proměnné explicitně přiřadit hodnotu ```null```
- Např. ```pocatek = null;```
- Tím ztratíme referenci na instanci a Garbage Collector ji časem smaže a uvolní tím paměť, kterou instance zabírá
- V Javě neexistuje příkaz pro explicitní smazání instance (a tím pádem „ruční“ uvolnění paměti)
- POZOR! Pokud má referenční proměnná hodnotu ```null``` (tj. neukazuje na žádnou instanci) nelze přes tuto proměnnou přistupovat k atributům a metodám instance (protože tam žádná instance není)
- Pokus o přístup vede k chybě ```NullPointerException``` za běhu programu (nikoliv při překladu)
- Pokud se může stát (v závislosti na předchozím kódu), že referenční proměnná může být ```null```, nebo může ukazovat na instanci, je vhodné před přístupem k proměnným a metodám instance otestovat, zda je referenční proměnná různá od ```null``` např. ```if (pocatek != null)```
### Atributy (proměnné) instance
- Protože třídy jsou abstrakce objektů z reálného světa, atributy typicky odpovídají vlastnostem těchto objektů
- Jako atributy jsou reprezentovány pouze ty vlastnosti, které jsou důležité z hlediska výpočtu (funkce programu)
- Každá instance může mít (a typicky má) v atributech uloženy jiné hodnoty
- Atributy (proměnné) instance jsou deklarované uvnitř třídy ale MIMO metody
- V deklaraci NEMAJÍ uvedeno klíčové slovo ```static```
- Naprostá většina proměnných v dosavadních programech byla definována uvnitř metod (hlavně ```main()```) a jednalo se tedy o lokální proměnné
- Pokud byly dosud proměnné deklarované vně metod, jednalo se o statické proměnné třídy (s klíčovým slovem ```static``` např. používané deklarace ```Scanner```u pro čtení z klávesnice)
- Dokumentační komentáře jsou typicky jednořádkové a stručně popisují účel proměnné
- Atributy se typicky deklarují na začátku třídy (před všemi metodami)
- Kvůli přehlednosti
- Atribut má viditelnost (je použitelný) přes celou třídu (i před místem deklarace), podobně jako metody
- Atributy (proměnné) instance mohou být libovolného datového typu (primitivní datový typ, třídy nebo pole) - Není žádné omezení
- Implicitní inicializace atributů (proměnných) instance
- U lokálních proměnných (deklarovaných uvnitř metod) bylo doporučeno provést inicializaci hned při deklaraci (např. ```int i = 0;```), aby se nestalo, že se pokusíme číst z proměnné její hodnotu, která ale nebyla nastavená
- U atributů (proměnných) instance to není nutné, protože jsou automaticky (implicitně) inicializovány na ```0, 0.0, false``` nebo ```null```, v závislosti na datovém typu
- Doplnit explicitní inicializaci je možné, ale není to nutné ani vhodné
#### Konstanty instance
- Ve třídě je možné definovat i konstanty instance
- Stejně jako pro lokální konstanty a statické konstanty třídy je nutné přidat klíčové slovo ```final```
- ```final datovýTyp JMÉNO_KONSTANTY = hodnota; ```
- V deklaraci chybí klíčové slovo ```static```
- Např. ```final int MAXIMALNI_SIRKA = 1280;```
- Hodnota konstanty instance nemusí být, stejně jako lokální konstanty, nastavena při deklaraci, ale může být **nastavena později** u **konstanty instance** to však lze provést **pouze v konstruktoru**
- Vždy však lze **hodnota konstanty nastavit pouze jednou**
- Mnohem častěji se využívají statické konstanty třídy
### Metody instance
- Metody instance představují **operace nad atributy instance**
- Platí pro ně téměř stejná pravidla, jako pro statické metody třídy
#### Deklarace metody instance
- Deklarace se liší od dosud probraných statických metod třídy pouze chybějícím klíčovým slovem ```static``` v hlavičce metody
- ```přístupovéPrávo návratováHodnota název(parametry)```
- Např. ```public double urciVzdalenost(Bod2D b)```
#### Volání metod instance
- Pokud voláme metodu instance ve stejné třídě, v jaké je deklarována (tj. voláme ji z jiné metody téže třídy), voláme ji pouze jejím jménem a hodnotami parametrů
- ``metoda(parametry)``
- Stejné jako u statických metod třídy
- Např. ```int mocnina = naDruhou(x);```
- Pokud použijeme metodu vně třídy, ve které je deklarována, musíme před název metody přidat název referenční proměnné ukazující na instanci, nad níž chceme metodu zavolat
- ```referenčníProměnná.metoda(parametry);```
- Na rozdíl od statické metody třídy, kdy se používá název třídy
### Metody a atributy instance a třídy
- Z předchozích kapitol vyplývá, že existují dva druhy metod a dva druhy atributů
- Metody a atributy (proměnné) instance
- (Statické) metody a atributy (proměnné) třídy
#### Porovnání vlastností metod a atributů instance a třídy
- Metody a atributy (proměnné) **instance** (bez ```static```)
- Každá instance má vlastní hodnoty atributů (proměnných)
- K proměnným instance se přistupuje přes konkrétní referenční proměnnou ukazující na konkrétní instanci
- Metody instance se vně své třídy (kde jsou deklarovány) volají nad konkrétní referenční proměnnou ukazující na konkrétní instanci
- Metody instance mohou uvnitř své třídy volat jiné metody instance i metody třídy a přistupovat k proměnným instance i třídy
- Při správném objektovém návrhu je to naprostá většina atributů a metod
- Metody a atributy (proměnné) **třídy** (se ```static```)
- Každá proměnná třídy má jen jedno paměťové místo a může tak mít jen jednu hodnotu, bez ohledu na to, kolik instancí třídy existuje
- Paměťové místo pro proměnnou třídy existuje, i když žádná instance ještě neexistuje
- K proměnným třídy se vně jejich třídy přistupuje přes název třídy
- Metody třídy se vně své třídy volají nad názvem třídy
- Metody třídy mohou uvnitř své třídy volat pouze metody třídy a přistupovat pouze k proměnným třídy (metody a proměnné instance deklarované v téže třídě, tj. bez ```static```, jsou pro ně nepřístupné)
- Při správném objektovém návrhu jich není mnoho
- Výjimkou jsou konstanty třídy, které jsou podstatně častější než konstanty instance
#### Použití metod a atributů (proměnných) instance
- Atributy instance obsahují data konkrétní instance třídy
- Metody instance provádějí operace nad těmito konkrétními daty
- Díky tomu, že metody instance mají přístup k atributům instance přímo, tato data se nemusí předávat (a nepředávají) jako parametry metod
- Metody instance jsou poměrně často bez parametrů, protože většinou pracují s proměnnými instance, ke kterým mají přímý přístup (aniž by musely být předávány jako parametry metody)
- Pokud v programu od třídy vytvářím instanci či instance, většina atributů a metod bude instance, nikoliv třídy
- Výjimku tvoří konstanty instance, které se v programech používají minimálně
#### Použití metod a proměnných třídy
- Použití konstant třídy
- Konstanty v dané třídě jsou ve většině případů stejné pro všechny instance => **není vhodné používat konstanty instance**
- **Konstanta třídy** zabírá **pouze jedno paměťové místo** (na rozdíl od konstanty instance, kde je zabráno tolik paměťových míst, kolik je instancí)
- Pro získání hodnoty konstanty třídy se nevytváří instance, přistupuje se k ní přes název třídy (např. ```Math.PI```)
- Uvnitř třídy není název třídy nutný
- Konstanty mají obvykle přístupové právo ```public```
- Konstantě třídy lze přiřadit hodnota pouze přímo v deklaraci, není možné ji inicializovat později
- Použití proměnných třídy
- Málo časté
- Hodí se, pokud potřebujeme, aby byla proměnná jen jedna pro všechny instance
- Např. doporučené použití třídy ```Scanner``` pro čtení ze standardního vstupu
- ```public static Scanner sc;```
- Aby ```Scanner``` fungoval správně na standardní vstup, je potřeba mít jen jeden v celém programu. Tento požadavek splňuje právě statická proměnná ```sc```, přes kterou pak lze provádět čtení kdekoliv v programu
- Do proměnné ```sc``` se přiřadí instance hned na začátku metody ```main()``` a tato instance se pak používá pro veškeré čtení
- Použití metod třídy
- Vstupní bod programu metoda ```main()``` je metoda třídy (statická)
- To vychází z toho, že na začátku programu není k dispozici instance žádné třídy, a tedy nemůže být spuštěná metoda instance
- Pokud potřebuji pomocnou metodu, kterou volám v metodě ```main()```, musí to být rovněž metoda třídy (statická)
- Zde stojí za zvážení, jestli není lepší v metodě ```main()``` vytvořit instanci a nad ní pak volat libovolné metody instance
- Metody, u kterých se nevyplatí vytvářet instanci
- Je mnoho metod, které realizují nějaký výpočet, ke kterému nepotřebují instanční proměnné ani jiné vlastnosti instance (např. matematické výpočty metody třídy ```Math```)
- U takových metod je vhodné, aby byly metody třídy (statické), protože se nemusí vytvářet instance a volají se přímo nad názvem třídy
- Více takových metod může být deklarováno v tzv. utility třídě
- Volání je pak možné z jakékoliv metody (třídy či instance)
#### Mechanizmus předání referenčních parametrů metod
- Metody instance i statické metody třídy mají stejný mechanizmus předávání hodnot parametrů metod
- Hodnoty parametrů se předávají hodnotou
- Platí jak pro parametry primitivních datových typů, tak i referencí (typu třídy, ukazujících na instance)
- Stejný mechanizmus má ale různé důsledky
- Pro primitivní datové typy se změna hodnoty formálního parametru uvnitř metody neprojeví vně metody (protože hodnota parametru je pouze kopií)
- Obsah referenční proměnné je však pouze odkaz ukazující na instanci (na rozdíl od proměnné primitivního datového typu, která obsahuje hodnotu přímo, např. celé číslo)
- Pokud překopírujeme odkaz, bude pořád ukazovat na stejnou instanci => změny provedené v této instanci SE PROJEVÍ i vně metody
### Konstruktor
- Při vytváření instance třídy operátorem ```new``` je vhodné nastavit počáteční hodnoty atributů této instance (objektu) pro to slouží tzv. konstruktor
- Konstruktor
- Speciální metoda (instance) pro inicializaci objektu
- Musí se jmenovat stejně jako třída (včetně velikosti písmen)
- Nemá žádnou návratovou hodnotu (ani ```void```)
- Podle toho se pozná od ostatních metod (a podle názvu jako třída
- Při vytváření instance za ```new``` ve skutečnosti voláme konstruktor
- Protože se jmenuje stejně jako třída, vypadá to, že uvádíme třídu
- Konstruktor může být bez parametru, nebo může mít „libovolné“ množství a typ parametrů (jako běžná metoda)
- Konstruktor nemusí být ve třídě explicitně uveden, ale pokud je, typicky obsahuje inicializaci atributů instance
- Často s předáním hodnot atributů pomocí formálních parametrů konstruktoru
- Inicializace atributů nemusí být jen hodnotami formálních parametrů, mohou se např. pouze připravovat složitější datové struktury pro další výpočty
- Konstruktor může být (a často bývá) přetížen
- Umožňuje různou inicializaci atributů instance
#### Proměnná ```this```
- V konstruktoru (ale i setrech a dalších metodách) se typicky využívá speciální referenční proměnná ```this```
- Referenční proměnná ```this```
- Je dostupná v každé instanci a ukazuje na „tuto“ instanci (tj. na sebe sama)
- Všechny metody instance volané uvnitř své třídy (tj. z jiných metod instance, bez uvedení referenční proměnné, nad kterou jsou volány) jsou implicitně volány nad proměnnou ```this```, to samé platí pro atributy instance
- Díky tomu je možné používat metody a atributy instance uvnitř jejich třídy bez uvedení instance (implicitně se použije ```this```)
- Explicitní použití ```this``` umožňuje přístup k atributům instance, pokud jsou zastíněny lokální proměnnou nebo parametrem metody/konstruktoru se stejným názvem
- Parametry konstruktoru sloužící pro předání počátečních hodnot atributů instance se typicky jmenují stejně
- Díky ```this``` není nutné vymýšlet jiné názvy formálních parametrů metod/konstruktorů
- Explicitní uvedení ```this``` je možné u metod a atributů instance vždy (i když nedochází k zastínění), ale není to nutné ani příliš vhodné
- přetížení konstruktoru
- Při přetěžování konstruktoru je možné volat jiný konstruktor téže třídy
- Volání jiného konstruktoru musí být první příkaz v konstruktoru
- Volá se pomocí ```this(parametry);```, nikoliv jménem konstruktoru
- Není třeba opakovat kód konstruktoru => používá se běžně
#### Implicitní konstruktor
- Pokud ve třídě není žádný konstruktor uveden volá se při vytváření nové instance implicitní konstruktor bez parametrů
- Tento konstruktor bez parametrů zajistí vytvoření instance v paměti
- Atributy instance jsou implicitně inicializovány na ``0, 0.0, false`` nebo ```null``` podle datového typu
- POZOR! Pokud do třídy přidáme libovolný explicitní konstruktor, implicitní konstruktor nebude vytvořen!
- Pokud potřebujeme i konstruktor bez parametrů jako doplněk k dalším konstruktorům, musíme ho rovněž explicitně napsat
- Pak je možné použít konstruktor bez parametrů (ale nejedná se o implicitní konstruktor, protože je ve třídě přímo napsaný)
### Zapouzdření a přístupová práva
- Atributy mohou být přístupné z vnějšku třídy
- Tento postup není vhodný, protože umožňuje změnu atributů bez jakékoliv kontroly, což umožňuje mj. zadat neplatné hodnoty
- **Zapouzdření** (encapsulation)
- Atributy objektu jsou **skryté před vnějšími vlivy** pomocí **přístupových práv**
- Pokud je potřeba změnit nastavení atributů, provádí se to prostřednictvím metod, které mohou obsahovat kontroly tzv. ```setry```
- Tyto metody by měly existovat pouze pro atributy, u kterých chceme jejich změnu z vnějšku třídy umožnit
- Pokud je potřeba získat hodnoty atributů, jsou zpřístupněny metodami nazvanými ```getry```
- Tyto metody by měly existovat pouze pro atributy, jejichž hodnota má být přístupná z vnějšku třídy
- I metody mohou mít nastavená přístupová práva tak, aby je nebylo možné volat z vnějšku třídy
- Typicky pomocné metody
#### Přístupová práva
- Přístupová práva určují, odkud lze k dané metodě nebo atributu přistoupit
- Klíčová slova určující přístupová práva se píší na začátek deklarace
- U atributů před datový typ
- Např. ```private int pocetClenu;```
- U metod před návratovou hodnotu nebo ```void```
- Např. ```public int naDruhou(int x)```
- Přístupová práva (od nejméně po nejvíce restriktivní)
- ```public```
- Metoda/atribut je přístupný odkudkoliv (ze stejné třídy, z jiné třídy stejného balíku, z jiné třídy jiného balíku)
- Typicky se používá pro metody
- ```protected```
- Metoda/atribut je přístupný ze stejné třídy, z jiné třídy stejného balíku a z potomka třídy (viz předmět KIV/OOP)
- Neuvedeno (přístupové právo není explicitně uvedeno)
- Metoda/atribut je přístupný ze stejné třídy a z jiné třídy stejného balíku
- ```private```
- Metoda/atribut je přístupný pouze ze stejné třídy
- Typicky se používá pro atributy
- Přístupová práva u třídy (a také rozhraní viz předměty KIV/OOP a KIV/PPA2)
- ```public```
- Třída musí být v souboru odpovídající názvu třídy
- Neuvedeno
- Třída může být v jiném souboru, který neodpovídá názvu třídy
- Více tříd pak může být v jednom souboru, ale maximálně jedna může být ```public``` (a její název pak odpovídá názvu souboru)
- Pak ale není viditelná z jiného balíku => nepoužívat
- Jiná přístupová práva pro třídy možná nejsou
#### Getry a setry
- Metody pro přístup k atributům
- Getry začínají slovem ```get``` (anglicky „získat“), v případě atributu typu boolean slovem ```is``` (anglicky „je“)
- Setry začínají slovem ```set``` (anglicky „nastavit“)
- Slova ```get``` a ```set``` se používají, i když píšeme zdrojový kód česky
- Je to konvence pojmenování, která se dodržuje
- Jinak jsou to běžné metody
- Getry
- Hlavička přesně daná pro daný atribut
- ```public datovýTypAtributu getAtribut()```
- ```public boolean isAtribut()```
- Např. ```public int getX()```
- Např. ```public boolean isPrazdny()```
- Vrací hodnotu atributu, typicky obsahují jedinou řádku s příkazem ```return```
- Setry
- Hlavička přesně daná pro daný atribut
- ```public void setAtribut(datovýTypAtributu atribut)```
- Např. ```public void setX(int x)```
- Nastaví hodnotu atributu
- Obsahuje přiřazení hodnoty do atributu předané přes formální parametr setru
- Typicky se používá referenční proměnná ```this``` jako v konstruktoru
- Typicky by měl obsahovat **kontrolu**, **zda je hodnota formálního parametru platná** (přípustná)
- POZOR! Nastavit hodnotu pouze, pokud je platná, a jinak neudělat nic není nejšťastnější řešení **reálně se řeší pomocí výjimek**
- Pokud tuto **kontrolu neobsahuje**, pak se vlastně o **zapouzdření nejedná**, protože si můžeme z vnějšku třídy dělat s atributem, co chceme (byť prostřednictvím getru a setru)
- Pokud tuto kontrolu dělá, **měl by být setr použit i v konstruktoru** místo přímého přiřazení
- Přiřazení je bez kontroly, což umožňuje zadat neplatnou hodnotu přes formální parametry konstruktoru
- Běžné metody instance (ne getry a setry) mohou měnit více atributů najednou, čímž vyjádří jednu změnu stavu instance
- Pokud jsou na sobě atributy závislé a neměly by se měnit každý zvlášť, pak by pro ně neměly existovat setry a místo toho by měla existovat metoda měnící konzistentně všechny závislé atributy najednou
### Textová reprezentace objektu
- Objekty (instance), mohou být velmi komplikované (obsahovat mnoho různých atributů), často je ale **potřeba získat textovou reprezentaci** objektu (ve formě řetězce ```String```)
- **Pro výpis objektu** do příkazové řádky velmi často během ladění programu
- **Pro zobrazení objektu** např. v seznamu v grafickém uživatelském prostředí (GUI)
- Jsou i další použití
- Vypisování hodnot jednotlivých atributů ručně je zdlouhavé, pokud je atributů více, a kód pro výpis je navíc v jiné třídě => využívá se metoda ```toString()```
#### Metoda toString()
- Metoda vracející textovou reprezentaci objektu (instance)
- Hlavička metody ```public String toString()```
- Tato metoda je implicitně v každé instanci (je zděděna od třídy ```Object``` viz předmět KIV/OOP)
- Vrací řetězec popisující danou instanci
- Metoda pouze VRACÍ řetězec, sama ho NEVYPISUJE
Tato metoda se volá, pokud chceme objekt (instanci) vypsat pomocí metody ```System.out.println()```
- **Implicitní implementace**
- Vrací řetězec obsahující název třídy, zavináč a číslo určující konkrétní instanci
- Např. ```Bod2D3@15db9742```
- Neobsahuje informace o stavu třídy (např. hodnoty atributů)
- **Vlastní implementace**
- Implicitní metodu lze překrýt **vlastní implementací**
- Stačí ve třídě vytvořit **metodu se stejnou hlavičkou**
- Před metodu je vhodné napsat ```@Override``` indikující, že **metoda je překryta** (overridden)
- Není to nutné, ale např. Eclipse tuto entitu doplní automaticky, pokud necháme metodu ```toString()``` vygenerovat
- Bližší informace viz předmět KIV/OOP
- Metoda musí vracet řetězec, ale ten může obsahovat cokoliv
- Typicky obsahuje hodnoty atributů (při ladění programu), ale záleží na tom, na co chceme textovou reprezentaci třídy použít
- Příklad typické metody ```toString()```
### Porovnání objektů
- Objekty (instance) obecně nejsou uspořádané jako základní datové typy, operátory ```„>“, „>=“, „<“, „<=“``` tedy nelze použít
- Lze však použít porovnání na rovnost (operátor ```„==“```) a také různost (operátor ```„!=“```)
- POZOR! Má jiný než očekávaný význam
- Výsledkem porovnání je **true**, **pokud se jedná o stejnou instanci** (tj. porovnávané referenční proměnné odkazují na stejnou instanci). **Pokud se nejedná o stejnou instanci**, je výsledkem porovnání **false**
- I když mají **dvě instance stejné třídy stejné hodnoty** všech atributů, výsledek je **false**
- Často je ale potřeba zjistit, zda jsou objekty shodné podle hodnot atributů (některých nebo všech)
- Lze dělat ručně porovnáváním jednotlivých atributů, ale pro více atributů zdlouhavé a kód pro porovnání je v jiné třídě => využívá se metoda ```equals()```
#### Metoda equals()
- Metoda slouží **k porovnání objektu** (instance) **s objektem stejné třídy**
- Hlavička metody ```public boolean equals(Object o)```
- Tato metoda je implicitně v každé instanci (je zděděna od třídy ```Object``` viz předmět KIV/OOP)
- Stejně jako metoda ```toString()```
- Metoda vrací ```true```, pokud jsou instance shodné a ```false```, pokud jsou instance rozdílné
- **Co je shodné a rozdílné, určuje kód metody**
- Typicky **se porovnávají hodnoty atributů**
- **Implicitní implementace**
- Chová se stejně jako operátor „```==```“
- Vrací **true** pouze v případě, že je **stejná instance**
- **Explicitní implementace**
- Implicitní metodu lze překrýt **vlastní implementací**
- Stačí ve třídě vytvořit metodu se stejnou hlavičkou
- Před metodu je vhodné napsat ```@Override``` indikující, že metoda je překryta (overridden)
- Existují doporučení, jak má kód metody ```equals()``` vypadat (viz předmět KIV/OOP)
- Porovnávaná instance je v parametru, který je typu (třídy) ```Object```
- Aby bylo možné číst atributy porovnávané instance, je potřeba proměnnou explicitně přetypovat na typ třídy naší instance
- Přetypování se zapisuje stejně jako u základních datových typů (název třídy v kulaté závorce)
- Při pokusu o přetypování na nesprávný typ dojde k chybě za běhu programu
- Pak je možné porovnávat jednotlivé atributy
- Příklad implementace metody ```equals()```
### Výčtový typ
- Výčtový typ v Javě je sofistikovanější řešení pojmenovaných konstant
#### Základní použití výčtového typu
- Základní použití výčtového typu se hodí v případě, kdy
- Máme více konstant, které spolu souvisí
- Jejich hodnota je irelevantní
- Deklarace výčtového typu
- Deklaruje se podobně jako třída, místo klíčového slova ```class``` se použije klíčové slovo ```enum```
- Pravidla pojmenování jsou stejná jako pro třídu počáteční písmeno velké, počáteční písmena všech dalších slov víceslovného názvu velká
- Pokud je označen přístupovým právem ```public```, musí být v samostatném souboru, jehož název odpovídá názvu výčtového typu
- Na začátku obsahuje konstanty, což jsou jednotlivé hodnoty výčtového typu
- Pravidla pojmenování stejná jako pro konstanty všechna písmena velká, oddělovač slov ve víceslovném názvu je podtržítko
- Konstanty jsou odděleny čárkami
- Použití výčtového typu
- Výčtový typ můžeme využít pro deklarování libovolné proměnné (lokální, instance, třídy), jako návratovou hodnotu metody, atd. stejně jako jakýkoliv jiný datový typ (základní, třída, pole)
- Do proměnné výčtového typu lze přiřadit pouze jednu z konstant definovaných v deklaraci výčtového typu nebo hodnotu ```null```
- Při použití konstanty je třeba použít název výčtového typu
- ```VýčtovýTyp.KONSTANTA```
- Podobně jako u konstant třídy
- Hodnoty výčtového typu lze porovnávat operátorem „```==```“ s očekávaným výsledkem (na rozdíl od instancí třídy)
- Hodnoty výčtového typu lze přímo vypsat
- Vypíše se přímo název konkrétní konstanty
#### Pokročilé použití výčtového typu
- Výčtový typ má větší možnosti než bylo popsáno
- Může obsahovat proměnné a metody, které se pak vážou k jednotlivým hodnotám výčtového typu
- Např. u typu ```HodnotaKaret``` by bylo možné u každé hodnoty uvést bodovou hodnotu karet
- Podrobnosti viz předmět KIV/OOP