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

397 lines
29 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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