# Metody - Naprostá většina programů je netriviální a rozsáhlá - Často potřebujeme jeden výpočet provést vícekrát - Pokud všechen výkonný kód napíšeme jen do metody ```main```(), budou se části kódu opakovat - Potřeba dekompozice - Rozdělení problému na menší podproblémy - Tyto podproblémy lze rozdělit ještě na menší podproblémy - Tak postupujeme dále, až dostaneme elementární podproblémy, které jsou snadno řešitelné => postupujeme hierarchicky odshora dolů - Snadno řešitelné elementární podproblémy mohou být reprezentovány metodami - Použití metod - Program se snáze navrhuje - Je rozdělen na elementární části reprezentované metodami - Je možné vytvářet program po krocích - Zdrojový kód je přehlednější - V daném místě se lze soustředit jen na jednu konkrétní část algoritmu ### Popis metod a terminologie - metody jsou úseky kódu (podprogramy), které provádějí nějaký výpočet - Metody by neměly být příliš dlouhé (cca na jednu obrazovku) a měly by dělat jednu jasně definovatelnou činnost popsanou jejich názvem - Je třeba rozlišovat deklaraci/definici metody a volání/použití metody ### Deklarace metody - Deklarace metody znamená, že vytvoříme (napíšeme) metodu - včetně jejího názvu a výkonného kódu - POZOR! – Tento kód se však provede až při volání metody - Každá metoda se skládá z hlavičky a těla - Hlavička metody - Obsahuje „popis vlastností“ metody včetně jejího jména - ``` právo static návratováHodnota název(parametry) ``` - Např. ``` public static double naDruhou(double x) ``` - ```public ``` je přístupové právo - ```static ``` značí, že se jedná o statickou metody třídy - Existují i metody bez ```static```, tzv. metody instance, kterých je ve skutečnosti většina - Název metody začíná malým počátečním písmenem, každé další slovo víceslovného názvu začíná velkým písmenem - Podobně jako u názvu proměnných - U dokumentačního komentáře metody se uvádí alespoň jedna řádka popisující účel metody, případné parametry metody a návratová hodnota jsou popsány na dalších řádkách - např.: ```java /** * Ukazka deklarace metod - vypocet vzdalenosti dvou bodu v rovine * @author Tomas Potuzak * @version 1.0 (2018-08-13) */ ``` - Tělo metody - Obsahuje výkonné příkazy uzavřené do složených závorek - V Javě se otevírací závorka píše na řádku hlavičky metody - Metoda je jednoznačně určena třídou, ve které je deklarována, svým názvem, počtem, typem a pořadím svých parametrů a návratovou hodnotou - Přesto se ve vysvětlujícím textu (nikoliv ve zdrojovém kódu) běžně používá pouze název metody se závorkami (např. ``` naDruhou ```()), pokud nehrozí záměna za jinou metodu - Každá metoda musí být deklarována přímo uvnitř třídy - Není možné deklarovat metodu mimo třídu - Není možné deklarovat metodu uvnitř jiné metody - Metody se typicky deklarují po deklaraci proměnných (např. deklarace ```Scanner```u) kvůli přehlednosti - Mohou být ale deklarovány kdekoliv uvnitř třídy - Pořadí deklarace metod **je** (v Javě) **irelevantní**, každá metoda je platná (je viditelná) v celé třídě => metoda může být deklarována až za místem, kde již byla volána ### Volání (použití) metody - Volání metody znamená, že se provede kód umístěný v těle metody na místě programu, kde metodu voláme (použijeme) - Pokud chceme metodu použít (tj. chceme, aby provedla svou činnost (výpočet) na určitém místě), použijeme její jméno a do závorek napíšeme hodnoty skutečných parametrů, které nahradí formální parametry v hlavičce metody - Pokud použijeme metodu ve stejné třídě, jako ve které 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); ``` - Pokud použijeme metodu vně třídy, ve které je deklarována, musíme před název metody přidat název třídy, ve které je deklarována (tečková notace) - ``` Třída.metoda(parametry); ``` - Toto platí pouze pro metody označené klíčovým slovem ```static``` ### Lokální proměnné - Jsou definovány **UVNITŘ** metod #### Viditelnost lokálních proměnných - Jsou viditelné (tj. mohu je používat pro čtení a zápis) **pouze uvnitř metody** - Jsou viditelné od místa (řádky), kde byly deklarovány - Jsou viditelné do konce bloku, ve kterém byly deklarovány - Rozdíl oproti proměnným definovaným UVNITŘ třídy, ale VNĚ metod (proměnné třídy), které jsou viditelné v rámci třídy i před místem deklarace (podobně jako metody) - Pokud jsou deklarovány přímo v těle metody (tj. ne uvnitř vnořeného bloku), jejich viditelnost končí s tělem metody - Pokud jsou definovány uvnitř vnořeného bloku (např. v příkazu if nebo v cyklu), jejich platnost končí koncem bloku - Zastíní proměnnou třídy (a instance) pokud se jmenuje stejně - Je možné deklarovat lokální proměnnou, která se jmenuje stejně jako proměnná třídy - Společný název (identifikátor) pak odkazuje na **LOKÁLNÍ** proměnnou, ne na proměnnou třídy - Potenciální zdroj problémů => je potřeba dát pozor, o jakou proměnnou se jedná (lokální/třídy/instance) - IDE nástroje většinou druh proměnné odlišují barvou či řezem písma pro větší přehlednost - Lokální proměnné ve vnořených blocích - Všechny lokální proměnné deklarované před vnořeným blokem jsou platné (viditelné) i v tomto bloku => nelze definovat novou lokální proměnnou se stejným názvem #### Inicializace lokálních proměnných - Lokální proměnné nejsou implicitně inicializovány na ```0, 0.0, false``` nebo ```null``` - Na rozdíl od proměnných třídy (a proměnných instance) - Je vhodné je inicializovat ručně (explicitně) - Např. ``` int i = 0; ``` ### Návratová hodnota metody a příkaz return - Existují **dva typy metod**: - Metody **s návratovou hodnotnou** (**funkce**) - Metody **bez návratové hodnoty** (**procedury**) #### Metody s návratovou hodnotou (funkce) - Metoda může vracet návratovou hodnotu, která může být libovolného typu (základní datový typ, třída, pole, ...) - Pokud metoda vrací návratovou hodnotu, jedná se o funkci - Typ je specifikován těsně před názvem metody - Pro určení návratové hodnoty uvnitř těla metody se používá příkaz (klíčové slovo) ```return```, za který se uvede výraz s odpovídajícím typem výsledné hodnoty - ```return výraz;``` - Výraz může být libovolně komplikovaný nebo se může jednat o samotnou proměnnou (nebo výjimečně i pojmenovanou/nepojmenovanou konstantu) - Volání metody s návratovou hodnotou - Výsledkem volání metody je její návratová hodnota, ale může mít i další efekty - Např. může ovlivnit hodnoty proměnných třídy (nebo mnohem častěji proměnných instance) - Pokud je primárním výsledkem volání metody (funkce) její návratová hodnota, je většinou volána jako součást výrazu - Pokud primárním výsledkem volání metody (funkce) je jiná činnost, kterou provádí, a návratová hodnota je (někdy) vedlejší, lze jí volat jako příkaz (tj. ne jako součást výrazu) - Vrácená hodnota se zahodí (nikam se nepřiřadí a nepoužije se) #### Metody bez návratové hodnoty (procedura) - Metoda nevrací žádnou návratovou hodnotu, pouze provede nějakou činnost => pak se jedná o proceduru - Při deklaraci metody se místo návratového typu uvede klíčové slovo void - Např. ```public void vypisNahodnaCisla()``` - Volání metody bez návratové hodnoty - Metoda se volá pouze jako příkaz, nemůže být součástí výrazu jako metoda s návratovou hodnotou #### Použití příkazu return - Příkaz return okamžitě ukončí metodu, bez ohledu na to, kde se v metodě nachází - Příkazů return může být v jedné metodě více (např. v každé větvi příkazu ```if```) - Pokud metoda vrací návratovou hodnotu (jedná se o funkci), nesmí existovat větev, ve které by příkaz return nebyl (došlo by k chybě překladu) - Za ním už se nesmí nacházet žádný příkaz, protože se nikdy nemůže provést (dojde k chybě překladu) - Např. pokud je použit v příkazu ```switch```, nemůžou být jednotlivé větve ukončeny příkazem ```break;```, protože tento příkaz je nedosažitelný - Příkaz ```return``` se může použít k předčasnému ukončení metody (např. proto, že parametr nemá platnou hodnotu) - Příkaz return se může použít i k předčasnému ukončení metody bez návratové hodnoty (procedury) - Pak se použije samotný ```return;``` ### Parametry metody - Metoda může mít „neomezené“ množství parametrů - Prakticky jich bývá pouze několik (žádný až cca 3 až 5) - Více parametrů typicky svědčí o špatné dekompozici problému - Parametry jsou popsány v závorce za názvem metody stejně jako deklarace proměnné typem a názvem - Parametry mohou být libovolného typu - Pokud má metoda více parametrů, jsou odděleny čárkou - U každé proměnné musí být explicitně uveden datový typ, i když je více parametrů stejného datového typu za sebou - Např. ```double static secti(double a, double b)``` #### Formální a skutečné parametry metody - Parametry definované v hlavičce metody (při deklaraci metody) se nazývají **formální parametry** - Při volání metody jsou v závorce uvedeny **skutečné parametry metody** - Musejí odpovídat počtem a datovým typem (ve správném pořadí) - Může se jednat o proměnné, pojmenované/nepojmenované konstanty a výrazy (datový typ výsledku výrazu musí odpovídat datovému typu formálního parametru) - Ve formálních parametrech (proměnných) jsou do metody předány hodnoty skutečných parametrů metody - Tyto hodnoty typicky ovlivňují chování metody - Formální parametry mají v těle metody všechny vlastnosti lokálních proměnných, typicky se ale jejich hodnoty jen čtou - Je možné do nich přiřadit hodnotu, tím se ale ztratí hodnota předaná do metody => do formálních parametrů nové hodnoty v těle metody nepřiřazovat #### Mechanizmus předání parametrů do metody - Parametry jsou předávány vždy **hodnotou** - Platí pro základní datové typy i reference - Hodnoty skutečných parametrů jsou překopírovány a vloženy do odpovídajících formálních parametrů, přes které jsou hodnoty dostupné v těle metody - Změnit hodnotu formálních parametrů v těle metody je možné, ale změna se nijak neprojeví vně metody - Kromě toho se přepíše hodnota předaná do metody ### Předávání řízení při volání metod - Pokud je program rozdělen na metody, neběží lineárně od první řádky po poslední - Při každém volání metody se „skočí“ na začátek těla metody a začne se provádět její kód - Tzv. „předávání řízení“ - Při dosažení konce těla metody se skočí zpátky na místo, odkud byla metoda volána, a pokračuje se dalším příkazem - Volání metody jako parametru jiné metody - Pokud metoda vrací návratovou hodnotu a tato hodnota je použita jako parametr volání další metody, je možné si ji uložit do pomocné proměnné a tu pak použít jako parametr další metody - Tento zápis je přehlednější - Je však také možné volat metodu přímo ve volání další metody - Tento zápis je úspornější, ale méně přehledný - Oba zápisy se běžně používají ### Přetěžování metod (overloading) - V jedné třídě může být deklarováno více metod se stejným jménem - Metody se pak nazývají přetížené (overloaded) #### Důvody k přetěžování metod - Přetížené metody obvykle dělají podobnou činnost, ale mírně se liší - Protože je možné metody přetížit, není nutné vymýšlet podobné názvy podobných metod, můžeme rovnou použít stejný název - Dělají stejnou činnost pro různý datový typ - Např. metoda ```Math.abs()``` je přetížena 4x pro typ ```int, long, float a double``` - Dělají stejnou činnost, ale s upřesněním - Typicky přibudou další parametry #### Požadavky na přetížené metody - Přetížené metody MUSÍ mít různé hlavičky - Musí se lišit počtem a/nebo typem a/nebo pořadím typů parametrů - Nestačí, aby se lišily jen návratovou hodnotou - Nestačí, aby se lišily jen názvem formálních parametrů - Názvy formálních parametrů nejsou podstatné – používají se v těle metody, ale při jejím volání je důležitý pouze jejich typ - Při volání překladač vybere podle skutečných parametrů metodu, která přesně odpovídá počtem, typem a pořadím parametrů