# 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