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

29 KiB
Raw Permalink Blame 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 Scanneru 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