# 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

