Předcházející kapitola
Obsah
Následující kapitola
Kapitola 3
Objektově orientovaný přístup
3.1 Objekt
Objekt je základní, jedinečnou a jednoznačně identifikovatelnou entitou, která je dána
- identitou - parametry, které odlišují objekt od ostatních objektů.
- chováním - služby, které objekt poskytuje vzhledem ke svému okolí (ostatním objektům).
Komunikace objektů probíhá pomocí zpráv. Zpráva je žádost,
aby objekt provedl jednu ze svých operací (metodu). Jak bude
vlastní operace provedena, záleží na objektu, který je příjemcem
zprávy.
Jak již bylo řečeno, Java je plně objektově orientovaný
jazyk, tedy i zde platí základní principy pro objektově
orientované programování. Komunikace mezi objekty pomocí zpráv je
umožněna díky využití principu zapouzdření. Tato vlastnost
objektu umožňuje přístup k datům objektu pouze na základě jeho
metod (chování).
Druhým principem, který využíváme, je
polymorfismus, tedy vlastnost díky níž může zpráva se stejným
jménem, zaslaná rozdílným objektům, způsobit rozdílné chování.
Praktický význam této vlastnosti je, že lze poslat zprávu se
stejným jménem na rozdílné objekty bez toho, aniž by nás zajímala
implementace metody a vnitřní struktura objektu.
Poslední ze
základních objektových praktik je dědičnost. Tento princip
umožňuje objektu získat strukturu lokálních dat a možné operace s
nimi od jim nadřazených objektů. Výhodou tohoto principu je vysoká
znovupoužitelnost kódu a možnost vytváření hierarchie objektů.
- Vytvoření objektu se děje pomocí klíčového slova new následovaného jménem třídy.
Př.: NovyObjekt nobjekt = new NovyObjekt(argumenty);
- Přístup k objektu se provádí pomocí jeho metod, tak, že za jménem objektu uvedeme jméno požadované metody
oddělené tečkou.
Př.: nobjekt.getName();
- Odstranění objektu je velkou předností Java technologie, protože objekt, který není používán delší dobu, je z paměti
odstraněn automaticky pomocí garbage collectoru. Díky tomuto mechanismu odpadají problémy a chyby spojené s
chybnou dealokací paměti.
- Kopírování objektu je možné pomocí metody clone(). Nutnou podmínku však je, aby příslušná třída implementovala
rozhraní Cloneable.
- Porovnávání objektů má dvě varianty:
- Pomocí operátoru ==, který zjistí, zda dvě proměnné odkazují na stejný objekt.
- Porovnání obsahu dvou rozdílných objektů umožňuje metoda equal(), která je definována ve spoustě tříd.
- Odkaz na aktuální objekt je možné provést pomocí
proměnné this. Typ objektu je dán třídou, jejíž metoda se
právě provádí.
Třída je zobecněním množiny objektů se shodnou vnitřní strukturou a chováním. Každý objekt je
instancí určité třídy. Protože třída je zobecněním objektů, uplatňují se v ní rovněž výše
popsané objektové principy (dědičnost, polymorfismus, zapouzdření), z nichž především dědičnost
nalézá největší uplatnění, neboť umožňuje vytváření hierarchie tříd.
Deklarace třídy má následující syntaxi
class JmenoTridy {
/* Telo tridy */
}
Chceme-li v Javě vytvořit novou třídu, musíme ji založit na
některé již existující. Základní třídou, z níž jsou přímo či
nepřímo odvozeny všechny třídy je třída Object definující
základní metody, které musí mít každý objekt v Javě. Není-li tedy
uveden předek právě vytvářené třídy, automaticky se předpokládá,
že je jím právě třída Object.
3.2.1 Konstruktory
Konstruktor je speciální metoda, která se volá pouze při vytváření objektu (viz.3.1) a slouží
k jeho inicializaci. Vlastnosti konstruktoru jsou pak následující
- Každá třída má nejméně jeden konstruktor. Jestliže není ve třídě definován žádný
konstruktor, pak Java automaticky vytvoří implicitní konstruktor bez argumentů.
- Jméno konstruktoru je vždy shodné se jménem třídy.
- Konstruktor automaticky vrací objekt, který je instancí uvedené třídy.
3.2.2 Třídní proměnné a metody
- Třídní proměnná - existuje pouze jedna její kopie v
dané třídě a ta je sdílena všemi instancemi této třídy.
- Třídní metoda
Jak již bylo zmíněno v předchozím textu, lze vytvářet hierarchii
tříd pomocí dědičnosti a tím zvyšovat či snižovat jejich
specializaci. Pokud chceme vytvořit třídu, která je odvozena z
jiné třídy než Object, musíme použít klíčové slovo
extends následované jménem třídy z níž dědíme.
class Potomek extends Rodic
{
/* Tělo nové třídy */
}
Java podporuje pouze jednoduchou dědičnost a vícenásobná dědičnost
je nahrazena mechanismem rozhraní.
Princip dědičnosti
sebou přináší výhodu znovupoužitelnosti kódu, tedy schopnost
potomka využívat metod jeho rodiče. K tomuto účelu slouží proměnná
super, která aktuálnímu objektu přiřadí typ rodičovské
třídy.
Slouží k zachycení společných vlastností tříd se zcela rozdílnou
implementací. Společnými vlastnostmi rozumíme konstanty a metody,
které dané třída musí implementovat. Rozhraní je tedy struktura,
obsahující seznam deklarací konstant a metod bez jejich
implementace. Zajišťuje tedy obalení protokolu metod bez omezení
na jejich implementaci. Deklarace rozhraní má následující syntaxi
public interface NovéRozhraní
{
/* Deklarace konstant a metod */
}
Třída, která pak dané rozhraní implementuje, musí obsahovat
definice všech metod a konstant obsažených v rozhraní. Třída může
implementovat i více rozhraní, čímž lze v Javě nahradit
vícenásobnou dědičnost.
public class NováTřída implements NovéRozhraní
{
/* Definice konstant a metod */
}
U rozhraní stejně jako u tříd, můžeme vytvářet jejich hierarchii
pomocí dědičnosti, čímž dostáváme více či méně specializovaná
rozhraní.
public interface NovéRozhraní extends StaréRozhraní
{
/* Deklarace nových metod pro NovéRozhraní */
}
3.3.2 Vztah Třída - Typ
3.4 Modifikátory a kvalifikátory
3.4.1 Modifikátory
| Modifikátor | public | default | protected | private protected | private |
|
|
| Přístupné jiným třídám, než podtřídám ze stejného balíku.
| ANO | ANO | ANO | NE | NE |
| Přístupné podtřídám ze stejného balíku.
| ANO | ANO | ANO | NE | NE |
| Přístupné jiným třídám než podtřídám z jiného balíku.
| ANO | NE | NE | NE | NE |
| Přístupné podtřídám z jiného balíku.
| ANO | NE | NE | NE | NE |
| Dědí je podtřídy ve stejném balíku.
| ANO | ANO | ANO | ANO | NE |
| Dědí je podtřídy v jiném balíku.
| ANO | NE | ANO | ANO | NE |
3.4.2 Kvalifikátory
- final
- volatile
- transient
- synchronized
- native
3.5 Abstraktní třídy
Abstraktní třídou nazveme jakoukoliv třídu obsahující abstraktní
metodu. Abstraktní metodou pak rozumíme funkci, která neobsahuje
žádný kód. Definujeme ji následovně
public abstract void function();
Z abstraktní třídy nelze vytvářet instance. Z podtřídy dané
abstraktní třídy lze vytvářet instance v případě, že daná podtřída
předefinuje všechny abstraktní metody rodičovské třídy.
3.6 Vnitřní třídy
Jsou vnořené nestatické třídy a lze je umístit do těla metody či
bloku. Nejsou přístupné zvenčí a nesmí obsahovat statické proměnné
a metody, ani deklarace rozhraní. Jsou analogií ukazatelů na funkce
v jazycích C/C++ nebo bloků ve Smalltalku. Vnitřní třídy mají přímý
přístup k soukromým statickým proměnným a metodám vnější třídy.
3.6.1 Lokální třídy
Jsou deklarovány uvnitř bloku a rovněž pouze v něm jsou viditelné.
Adaptéry
Jsou speciálním typem lokálních tříd a jejich úkolem je odchytit volání metod,
které používají jiný typ než aktuální objekt. Využití například v novém modelu
obsluhy událostí.
public class MyApplet extends Applet{
public void init(){
final Button b = new Button("Press me");
add(b);
class ButtonAdapter implements ActionListener{
public void actionPerformed(ActionEvent e){
b.setLabel("Pressed");
}
}
b.addActionListener(new ButtonAdapter());
}
}
Anonymní třídy
Jsou dalším speciálním typem lokálních tříd. Jejich deklarace je součástí
rozšířené syntaxe operátoru new.
public class MyApplet extends Applet{
public void init(){
final Button b = new Button("Press me");
add(b);
b.addActionListener(new ActionListener{
public void actionPerformed(ActionEvent e){
b.setLabel("Pressed");
}
});
}
}
Pokud je za operátorem new uvedeno jméno rozhraní, pak je třída přímým potomkem java.lang.Object,
jinak je bezprostřdní podtřídou uvedené třídy.
Předcházející kapitola
Obsah
Následující kapitola