FAV-ZCU/KIV PPA1/4. Metody.md

13 KiB
Raw Permalink Blame History

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ř.:
    /** 
    	* 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 Scanneru) 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ů