Seriál o výuce objektově orientovaného programování postupuje k podkapitolám 2.14 Atributy třídy (statické atributy) a 2.15 Metody třídy (statické metody). V minulém díle jsme se věnovali zapouzdření a lokální proměnné.
2.14 Atributy třídy (statické atributy)
Když jsme si v minulé kapitole hráli s geometrickými obrazci, ukazovali jsme si, že každý z nich poskytuje metody, které mohou pohnout se zadaným obrazcem o předem zadaný počet bodů. Tento počet byl uložen v atributu třídy nazvaném krok.
Terminologická poznámka:
Chceme-li ve zdrojovém kódu definovat nějaký atribut jako atribut třídy, přidáme mezi jeho modifikátory modifikátor static. Toť vše. Vzhledem k tomuto klíčovému slovu v deklaraci bývají atributy třídy často označovány jako statické atributy a atributy instancí jako nestatické atributy. Protože se tento termín oproti termínu „atributy třídy“ lépe skloňuje, budu jej v dalším textu často používat.
Doplňme třídu Smrk o atribut krok, který bude obsahovat počet bodů, o něž se obraz smrku posune po zavolání bezparametrických verzí posunových metod, a nadefinujme si hned metodu posunVlevo().
//== ATRIBUTY TRIDY ============================================================
private static int krok = 50;
//== OSTATNI METODY INSTANCI ===================================================
/**
* Posune obrazek smrku o krok bodu vlevo.
*/
public void posunVlevo()
{ //Pro posun vlevo musime zadat zapornou hodnotu
posunVpravo( -krok );
}//public void posunVlevo()
Úkol 1:
Doplňte třídu Smrk2 o metody posunVpravo(), posunNahoru() a posunDolu().
Úkol 2:
Doplňte statický atribut a bezparametrické posunové metody i do svých tříd Snehulak, Domek a Panak.
2.15 Metody třídy (statické metody)
Stejně jako atributy třídy existují i metody třídy. Jejich výhodou je, že je můžeme zavolat ještě před tím, než vznikne jejich první instance. Slouží proto často k přípravě prostředí, ve kterém následně instance vznikne, případně k definici metod, které nejsou na žádnou instanci vázány (takto je např. definována většina matematických funkcí). Jako metody třídy se (samozřejmě) definují také přístupové metody atributů třídy (i ty můžeme např. číst a nastavovat ještě před tím, než vznikne první instance dané třídy).
V naší třídě Smrk i ve vašich třídách Snehulak, Domek a Panak již je definován statický atribut krok. Definujme pro něj přístupovou metodu getKrok():
/**
* Vraci velikost kroku, o kterou se posune obrazek smrku
* pri volani bezparametrickych posunovych metod.
*
* @return velikost kroku v bodech
*/
public static int getKrok()
{
return krok;
}//public static int getKrok()
Úkol:
Doplňte stejnojmennou metodu do svých tříd Snehulak, Domek a Panak.
Upozornění:
Jak jsem řekl, metody třídy nezávisejí na žádné instanci a můžeme je volat ještě před tím, než první instance vznikne. Je proto logické, že v metodách třídy nemůžeme používat atributy a metody instancí, přesněji řečeno atributy a metody instancí kvalifikované implicitně nebo explicitně klíčovým slovem this. Překladač totiž nemá žádnou informaci o tom, která instance by se v daném okamžiku mohla za this skrývat.
Nic nám však nebrání vytvořit uvnitř metody novou instanci a volat pak její metody, protože ty již můžeme kvalifikovat konkrétní, existující instancí. Někdy si to ukážeme.
Kvalifikace atributů a metod třídy
I metody třídy je potřeba kvalifikovat, protože i u nich překladač potřebuje vědět, čí metodu překládá, aby se pak mohl obrátit na správné atributy. Můžeme je sice kvalifikovat instancí, ale jak jsme si před chvílí řekli, metody třídy je možno volat ještě před vznikem první instance (např. k tomu, abych nastavil velikost kroku při volání bezparametrických posunových metod žádnou instanci nepotřebuji). Pro jejich kvalifikaci nemůžeme použít ani klíčové slovo this, protože i to je určené k získání odkazu na instanci.
Jak si jistě domyslíte, onou instancí, jejíž atributy a metody definované třídě slouží, je vlastně celá třída. Asi vás proto nijak nepřekvapí, když vám prozradím, že metody třídy je možné kvalifikovat názvem třídy. Odtud by pak již mělo být vše jasné.
Pokud byste tedy např. chtěli ve svém programu získat plátno, abyste je mohli o něco požádat, zadáte příkaz:
Platno platno = Platno.getPlatno();
Tento příkaz definuje novou proměnnou (možná atribut, možná lokální proměnnou – to bychom poznali až podle okolního programu), která je odkazem na instanci třídy Platno a jmenuje se platno. V její deklaraci ji ihned přiřazujeme počáteční hodnotu, kterou získáme tak, že zavoláme metodu getPlatno(), která je (jak již víme) metodou třídy Platno a vrací odkaz na její jedinou instanci.
Ukažme si, jak bychom mohli takovouto proměnnou použít v programu. Předpokládejme, že máme ve třídě definovanou metodu setBarva(String) (tu byste určitě pro smrk či sněhuláka definovat dokázali – prostě nastavíte pro všechny trojúhelníky, resp. elipsy zadanou barvu). Definujme metodu schovejVPozadí(), která přebarví danou instanci na barvu pozadí použitého plátna. Definice by mohla vypadat následovně:
/**
* Prebarvi obrazek smrku barvou pozadi platna.
*/
public void schovejVPozadi()
{
//Metodu tridy kvalifikujeme tridou
Platno platno = Platno.getPlatno();
//Metodu instance kvalifikujeme instanci
String pozadi = platno.getBarvaPozadi();
horni.setBarva( pozadi );
stredni.setBarva( pozadi );
dolni.setBarva( pozadi );
}//public void schovejVPozadi()
Názvem třídy můžeme kvalifikovat nejenom metody třídy, ale i její atributy. Ukažme si to na příkladu metody setKrok(int), jejíž parametr bude mít stejný název jako nastavovaný atribut třídy:
/**
* Nastavi novou velikost kroku, o kterou se posune obrazek
* smrku pri volani bezparametrickych posunovych metod.
*
* @param krok nastavovana velikost kroku v bodech
*/
public static void setKrok( int krok )
{ //Atribut krok kvalifikujeme názvem tridy
Smrk.krok = krok;
}//public static void setKrok( int krok )
Poznámka:
Překladač není žádný hlupák. Objeví-li v kódu nekvalifikovaný odkaz na atribut nebo metodu třídy, nebude se je samozřejmě pokoušet hloupě kvalifikovat klíčovým slovem this, jak to dělal u atributů a metod instancí, ale rozumně se je pokusí kvalifikovat názvem třídy, v jejímž těle se daný kód nachází.
Kdybychom tedy v předchozí metodě použili parametr k a přiřazovací příkaz měl tvar:
krok = k;
překladač by identifikátor krok iniciativně kvalifikoval jako Smrk.krok, což je to, co jsme chtěli.
Úkol:
Doplňte stejnojmennou metodu do svých tříd Snehulak, Domek a Panak.
Rudolf Pecinovský
0 komentářů:
Okomentovat