V sedmém díle překladu oficiálního Java tutoriálu se zaměříme na stavební kámen objektově orientovaného programování, a to na objekty a třídy.
Třídy
Když jsme se poprvé ve 3. díle zmiňovali o třídách, vytvořili jsme na ukázku třídu jízdního kola se silničním a horským kolem jako potomky dané třídy.
Zde je příklad možné implementace třídy JizdniKolo pro získání přehledu o deklaraci třídy. Jednotlivé části dnešního dílu se podívají krok po kroku na deklaraci třídy. Nyní se, prosím, nesoustřeďte na detaily.
public class JizdniKolo {
// JizdniKolo má tři atributy
public int kadence;
public int prevod;
public int rychlost;
// JizdniKolo má jeden konstruktor
public JizdniKolo(int startovniKadence, int startovniRychlost, int startovniPrevod) {
prevod = startovniPrevod;
kadence = startovniKadence;
rychlost = startovniRychlost;
}
// JizdniKolo má čtyři metody
public void setKadence(int novaHodnota) {
kadence = novaHodnota;
}
public void setPrevod(int novaHodnota) {
prevod = novaHodnota;
}
public void brzdit(int kolik) {
rychlost -= kolik;
}
public void zrychlit(int kolik) {
rychlost += kolik;
}
}
Deklarace třídy HorskeKolo jako potomka třídy JizdniKolo může vypadat nějak takto:
public class HorskeKolo extends JizdniKolo {
// HorskeKolo přidává jednu atribut
public int vyskaSedadla;
// HorskeKolo má jeden constructor
public HorskeKolo(int startovniVyska, int startovniKadence, int startovniRychlost, int startovniPrevod) {
super(startovniKadence, startovniRychlost, startovniPrevod);
vyskaSedadla = startovniVyska;
}
// HorskeKolo přidává jednu metodu
public void setVyska(int vyska) {
vyskaSedadla = vyska;
}
}
HorskeKolo zdědí všechny atributy a metody třídy JizdniKolo a přidává atribut vyskaSedadla a meotdu pro nastavení (horská kola mají sedadlo, které se může pohybovat nahoru a dolů, podle současného terénu).
Deklarace členských proměnných
Existují různé druhy proměnných:
- Členské proměnné ve třídách, ty se nazývají atributy.
- Proměnné deklarované v metodách nebo blocích kódu, ty se nazývají lokální proměnné.
- Proměnné v deklaracích metod, ty se nazývají parametry.
Třída JizdniKolo používá následující řádky kódu pro definici svých atributů:
public int kadence;
public int prevod;
public int rychlost;
Deklarace atributů se skládá ze tří částí, v tomto pořadí:
- Žádný nebo více modifikátorů, jako je
public
neboprivate
- Typ atributu
- Název atributu
Atributy třídy JizdniKolo se nazývají kadence, prevod a rychlost a všechny jsou datového typu celé číslo (int
). Klíčové slovo public
identifikuje tyto členy jako veřejné, čili přístupné pomocí kteréhokoli objektu používajícího tuto třídu.
Modifikátory přístupu
První (nejvíce vlevo) modifikátor umožňuje určit, které ostatní třídy mají přístup k danému atributu. Nyní si povíme jen o public
a private
. Ostatní modifikátory přístupu probereme příště.
- Modifikátor
public
(veřejný) – atribut je přístupný ze všech tříd. - Modifikátor
private
(soukromý) – atribut je přístuný pouze z aktuální třídy.
V duchu zapouzdření je běžné dělat atributy soukromé. To znamená, že mohou být přímo přístupné pouze ze třídy JizdniKolo. Nicméně stále potřebujeme přístup k atributům. To může být uděláno nepřímo přidáním veřejných metod, které nám atributy zpřístupní:
public class JizdniKolo {
private int kadence;
private int prevod;
private int rychlost;
public JizdniKolo(int startovniKadence, int startovniRychlost, int startovniPrevod) {
prevod = startovniPrevod;
kadence = startovniKadence;
rychlost = startovniRychlost;
}
public int getKadence() {
return kadence;
}
public void setKadence(int novaHodnota) {
kadence = novaHodnota;
}
public int getPrevod() {
return prevod;
}
public void setPrevod(int novaHodnota) {
prevod = novaHodnota;
}
public int getrychlost() {
return rychlost;
}
public void brzdit(int snizeni) {
rychlost -= snizeni;
}
public void zrychlit(int zvyseni) {
rychlost += zvyseni;
}
}
Typy
Všechny proměnné musí mít typ. Můžete použít primitivní typy jako int
, float
, boolean
atd. Nebo můžete použít referenční typy, jako jsou řetězce, pole nebo objekty.
Názvy proměnných
Všechny proměnné, ať to jsou atributy, lokální proměnné nebo parametry, mají stejné pravidla a konvence, jak jsme si je popsali ve 4. díle.
V této lekci budeme používat stejná pravidla i pro pojmenovávání tříd a metod, s výjimkou toho, že:
- první písmenko názvu třídy by mělo být velké
- první (nebo jediné) slovo názvu metody by mělo být sloveso
Definice metod
Zde je příklad typické deklarace metody:
public double vypocitejOdpoved(int pocetKol, int pocetMotoru, double delka, double vahaVTunach) {
//zde budou vypocty
}
Jediné povinné části deklarace metody jsou typ návratové hodnoty, název, pár kulatých závorek a tělo uvnitř složených závorek.
Více obecně, deklarace metody má v pořadí těchto 6 částí:
- Modifikátory, jako jsou
public
,private
a další, o kterých si povíme později. - Typ návratové hodnoty – datový typ hodnoty vrácené metodou nebo
void
, pokud metoda nevrací žádnou hodnotu. - Název metody – pravidla pro názvy atributů se dají aplikovat i na metody, ale konvence je mírně jiná.
- Seznam parametrů v kulatých závorkách – čárkami oddělený seznam vstupních parametrů, předcházených jejimi typy, uzavřen mezi kulaté závorky. Jestliže metoda nepřebírá žádné parametry, musíte použít prázdné závorky.
- Seznam výjimek – bude probírán později.
- Tělo metody uzavřené mezi složené závorky – kód metody včetně deklarace lokálních proměnných patří sem.
Definice: Dvě z komponent deklarace metody tvoří signaturu (podpis) metody – název metody a typy parametrů.
Siganutra metody deklarované výše je tedy:
vypocitejOdpoved(double, int, double, double)
Pojmenování metod
Přestože jménem metody může být jakýkoli platný identifikátor, konvence omezují jména metody. Dle konvence může být názvem metody malými písmeny psané sloveso nebo víceslovný název, který začíná malými písmeny psaným slovesem, následovaný podstatnými jmény, přídavnými jmény atd. Ve víceslovných názvech by měla být první písmenka druhého a následujících slov velká. Zde je několik příkladů:
getBackground
compareTo
setX
bez
bezRychle
ziskejPozadi
ziskejKonecnaData
porovnejS
nastavX
jePrazdny
Typicky má každá metoda v rámci třídy své unikátní jméno. Nicméně v rámci třídy může mít více metod stejný název díky přetížení metod.
Přetížení metod
Programovací jazyk Java podporuje přetížené metody a může metody od sebe rozeznat pomocí odlišných signatur. To znamená, že v jedné třídě mohou existovat metody stejného jména jen v případě, že každá má jiný seznam parametrů (existují různé kvalifikace, o kterých si budeme povídat v příštích dílech).
Představme si, že máme třídu, která pomocí kaligrafie vykresluje různé typy dat (řetězce, celá čísla atd.) a obsahuje metody pro vykreslení každého datového typu. Je nešikovné použít pro každou metodu nový název – například, nakresliString
,
nakresliInteger
, nakresliFloat
atd. V programovacím jazyce Java, můžete použít pro kreslicí metody stejné názvy, ale musí se lišit jejich seznam parametrů. Tudíž ona kreslící třída bude definovat čtyři metody s názvem nakresli
, každá s jiným seznamem parametrů.
public class KreslicDat {
...
public void nakresli(String s) {
...
}
public void nakresli(int i) {
...
}
public void nakresli(double f) {
...
}
public void nakresli(int i, double f) {
...
}
}
Přetížené metody jsou odlišené podle počtu a typu parametrů, předaných metodě. Ve výše uvedeném příkladě, nakresli(String s)
a nakresli(int i)
jsou rozeznány jako unikátní metody, protože mají rozdílný typ parametru.
Nemůžete deklarovat více metod se stejným názvem a stejným počtem a typem parametrů, protože kompilátor by je nemohl od sebe odlišit.
Kompilátor nerozlišuje metody podle typu jejich návratové hodnoty, takže nemůžete deklarovat metody se stejnou siganturou, ačkoli by se lišily v typu návratové hodnoty.
Poznámka: Přetížené metody by se měly používat šetrně, protože jejich použití činí kód obtížně čitelný.
Definice konstruktorů ve Vašich třídách
Třída obsahuje konstruktory, které umožňují, aby se dle vzoru vytvořil funkční objekt.
Deklarace kontstruktorů vypadají jako deklarace metod, vyjma toho, že jako svůj název používají název třídy a nemají návratový typ. Například JizdniKolo
má jeden konstruktor:
public JizdniKolo(int startovniKadence, int startovniRychlost, int startovniPrevod) {
prevod = startovniPrevod;
kadence = startovniKadence;
rychlost = startovniRychlost;
}
Pro vytvoření objektu třídy JizdniKolo
nazvaného mojeKolo
je konstruktor zavolán operátorem new
:
JizdniKolo mojeKolo = new JizdniKolo(30, 0, 8);
new JizdniKolo(30, 0, 8)
vytvoří místo v paměti a inicializuje atributy.
Přestože má JizdniKolo
pouze jeden konstruktor, může mít další, včetně bezparametrového konstruktoru:
public JizdniKolo() {
prevod = 1;
kadence = 10;
rychlost = 0;
}
JizdniKolo tvojeKolo = new JizdniKolo();
zavolá bezparametrový konstruktor pro vytvoření obejktu třídy JizndniKolo
nazvaný tvojeKolo
.
Oba konstruktory mohou být definovány ve třídě JizdniKolo
, protože mají rozdílný seznam parametrů. Stejně jako u metod, Java rozlišuje konstrukotry podle počtu předaných parametrů a jejich typu. Nemůžete napsat dva konstruktory pro stejnou třídu, které by měly stejný počet parametrů a shodovaly by se i jejich typy, protože platforma by je nemohla odlišit. Toto by vedlo k chybě při kompilaci.
Nemusíte své třídě poskytnout žádný konstruktor, ale musíte být opatrní. Kompilátor automaticky poskytne bezparametrový, výchozí konstruktor jakékoli třídě bez konstruktorů. Tento výchozí kosntruktor zavolá automaticky bezparametrový konstruktor rodiče. Proto daný rodič musí mít bezparametrový konstruktor a je na Vás, abyste to zkontrolovali. Jestliže Vaše třída nemá explicitně uvedeného rodiče, poté se implicitně použije třída Object
, která má bezparametrový konstruktor.
Vy sami ve svém konstruktoru můžete zavolat konstruktor rodiče. Třída HorskeKolo
ze začátku dílu to dělá. Jak na to si povíme v příštích dílech.
V deklaraci konstruktoru můžete používat modifikátory přístupu, abyste mohli kontrolovat, které třídy mohou přistupovat ke konstruktoru.
Poznámka: Jestliže jiná třída nebude moci zavolat konstruktor MojeTrida
, nepůjde přímo vytvářet objekty třídy MojeTrida
.
Předávání informací metodě nebo konstruktoru
Deklarace metody nebo konstruktoru definuje počet a typy argumentů pro metodu nebo konstruktor. Například násladující metoda spočítá měsíční splátku osobní půjčky pomocí výše dluhu, úrokové míry, délky splácení dluhu (v počtu splátek) a konečnou výši dluhu:
public double spocitejSplatku(double vyseDluhu,
double mira,
double konecnaHodnota,
int pocetSplatek) {
double urok = mira / 100.0;
double docasna1 = Math.pow((1 + urok), -pocetSplatek);
double jmenovatel = (1 - docasna1) / urok;
double vysledek = (-vyseDluhu / jmenovatel)
- ((konecnaHodnota * pocetSplatek1) / jmenovatel);
return vysledek;
}
Tato metoda má čtyři parametry: výše dluhu, úroková míra, konečná hodnota dluhu a počet splátek. První tři jsou čísla s pohyblivou desetinnou čárkou a čtvrtý je celé číslo. Parametry se používají v těle metody a svou hodnotu získávájí přímo z předaných argumentů.
Poznámka: Parametry (jinak také formální parametry) odkazují na seznam proměnných v deklaraci metody. Argumenty (jinak také skutečné parametry) jsou aktuální hodnoty, které jsou předány, když je metody vyvolána. Když voláte metodu, argumenty musí odpovídat typem i pořadím deklarovaným parametrům.
Typy parametrů
Pro parametry metody nebo konstruktoru můžete použít libovolný typ. Toto zahrnuje primitivní datové typy, jako jsou celá či desetinná čísla, jak jste taktéž mohli vidět v metodě spocitejSplatku
, nebo referenční datové typy jako řetězce, objekty nebo pole.
Zde je příklad metody, která příjmá pole jako argument. V tomto příkladě metoda vytvoří nový objekt Polygon
a inicializuje jej z pole objektů Point
(předpokládáme, že Point
je třída, reprezentující souřadnice X a Y):
public Polygon polygonZ(Point[] rohy) {
// zde patří tělo metody
}
Poznámka: Programovací jazyk Java Vám neumožňuje předat metodu do jiné metody. Ale můžete předat objekt do metody a poté zavolat jeho metody.
Proměnný počet argumentů
Můžete použít konstrukci zvanou varargs pro předání proměnného počtu hodnot do metody. Deklarujte metody s proměnným počtem parametrů, pokud si nejste jisti, kolik hodnot příslušného typu bude do metody předáno. Je to zkratka ručního vytvoření pole (předchozí metoda by měla radši využít proměnného počtu parametrů než pole).
Pro použití proměnného počtu parametrů napište za jméno typu tři tečky (...
), poté mezeru a počet parametrů. Metoda poté může být zavolána s libovolným počtem argumentů včetně žádného.
public Polygon polygonZ(Point... rohy) {
int pocetStran = rohy.length;
double obdelnikPrvniStrany, delkaPrvniStrany;
obdelnikPrvniStrany = (rohy[1].x - rohy[0].x)*(rohy[1].x - rohy[0].x)
+ (rohy[1].y - rohy[0].y)*(rohy[1].y - rohy[0].y) ;
delkaPrvniStrany = Math.sqrt(obdelnikPrvniStrany);
// zbytek tela vytvori objekt Polygon
// a vrátí jej
}
Jak můžete vidět, uvnitř metody corners
vystupuje jako pole. Tato metoda může být zavolána buďto s polem, nebo s řadou argumentů. Kód těla metody získá parametr vždy jako pole.
Nejčastěji můžete vidět proměnný počet parametrů u metod, co tisknou nějaký výstup; například tato metoda printf
public PrintStream printf(String format, Object... args)
umožňuje tisknout libovolný počet objektů. Může být zavolána například takto:
System.out.printf("%s: %d, %s%n", jmeno, rc, adresa);
nebo také takto:
System.out.printf("%s: %d, %s, %s, %s%n", jmeno, rc, adresa, telefon, email);
nebo s rozdílným počtem argumentů.
Názvy parametrůKdyž deklarujete parametr metody nebo konstrukotru, musíte zadat název parametru. Toto jméno je používano uvnitř těla metody pro přístup k hodnotě příslušného argumentu.
Název parametru musí být unikátní v jeho jmenném prostoru. Nemůže být stejný jako název jiného parametru pro stejnou metodu nebo konstruktor a nemůže se jmenovat stejně, jako lokální proměnná, deklarovaná v těle metody nebo konstruktoru.
Parametr může mít stejné jméno jako jeden z atribut. V tomto případě se říká, že parametr zakrývá atribut. Zakrývání atributů činí váš kód méně čitelným, a proto se dle konvenvce doporučuje používat pouze v konstruktoru nebo metodě pro nastavení odpovídajících atributů. Pro příklad si prohlédněte následující třídu Kruh
a její metodu nastavitStred
:
public class Kruh {
private int x, y, radius;
public void nastavitStred(int x, int y) {
...
}
}
Třída Circle
má tři atributy: x
, y
a radius
. Metoda nastavitStred
má dva parametry, každý z nich má stejné jméno jako jeden z atributů. Každý parametr zakrývá atribut, který sdílí stejné jméno jako on. Takže jednoduché použití jmen x
nebo y
uvnitř těla metody odkazuje na parametr, nikoli
na atribut. Pro přístup k vlastnsoti musíte použít plně kvalifikované jméno. Jak na to, si povíme již v příštím díle seriálu.
Předávání argumentů primitivního typu
Primitivní argumenty jako int
nebo double
jsou metodě předány hodnotou. To znamená, že jakékoli změny, které s parametrem provedete, se týkají pouze aktuálního bloku. Když metoda skončí, parametry se odstraní a jakékoli změny se ztratí. Zde je příklad:
public class PredavaniPrimitivnichTypuHodnotou {
public static void main(String[] args) {
int x = 3;
//vyvolat volanaMetoda() s x jako argumentem
volanaMetoda(x);
// vytisknout x abychom videli, zda se neco zmenilo
System.out.println("Po zavolani metody, x = " + x);
}
// zmenit x v metode()
public static void volanaMetoda(int p) {
p = 10;
}
}
Když tento program spustíte, vysledek je:
Po zavolani zavolani metody, x = 3Předávání referenčních datových typů jako argumenty
Parametry referenčních datových typů, jako jsou objekty, jsou také předevávány metodě hodnotou. To znamená, že když se metoda ukončí, předaný referenční typ stále ukazuje na původní objekt. Nicméně hodnoty atributů objektu mohou být změněny v metodě, pokud mají příslušnou přístupovou úroveň.
Například následující ukázková metoda demonstruje, že může pohnout objektem třídy Circle
:
public void pohniSe(Circle circle, int deltaX, int deltaY) {
// pohne s kolem podle pravidla: x+deltaX, y+deltaY
circle.setX(circle.getX() + deltaX);
circle.setY(circle.getY() + deltaY);
// přiřadí nový odkaz do parametru
circle = new Circle(0, 0);
}
A metodu zavoláme s následujícími argumenty:
pohniSe(mujCircle, 23, 56)
Uvnitř metody circle
původně referuje na mujCircle
. Metoda změní souřadnice x a y objektu, na který circle
referuje (tj. mujCircle
) o 23 a 56. Tyto změny v objektu zůstanou i po zavolání metody. Poté je parametru circle
přiřazen odkaz na nový objekt Circle
s x = y = 0
. To přiřazení změní objekt v paměti, nicméně nebude to mít žádný efekt, až metoda skončí. Uvnitř metody se objekt, na který referuje circle
, změnil, ale když metoda skončí, mujCircle
bude stále odkazovat na stejný objekt
Circle
, na který ukazoval před zavoláním metody, protože byl metodě předán hodnotou.
Objekty
Typický program v jazyce Java vytváří hodně objektů, které mezi sebou, jak již víte, komunikují pomocí metod. Přes tyto interakce může program řešit různé úkoly, jako je implementace uživatelského rozhraní, spouštění animace, odesílání a příjmání informací po Internetu. Jakmile objekt dokončí práci, pro kterou byl vytvořen, jsou jeho zdroje automaticky recyklovány pro použití v jiných objektech.
Zde je malý ukázkový program, který vytvoří a použije tři objekty:
public class DemoVyytvoreniObjektu {
public static void main(String[] args) {
//Vytvoří objekt typu bod (Point)
Point bodJedna = new Point(23, 94);
//Vytvoří objekty typu obdelnik (Rectangle)
Rectangle ctverecJedna = new Rectangle(bodJedna, 100, 200);
Rectangle obdelnikDva = new Rectangle(50, 100);
//zobrazí informace o prvnim obdelniku
System.out.println("Sirka prvniho obdelniku: " +
obdelnikJedna.sirka);
System.out.println("Vyska prvniho obdelniku: " +
obdelnikJedna.vyska);
System.out.println("Obsah prvniho obdelniku: " +
obdelnikJedna.getArea());
//nastavi pozici druheho ctverce
obdelnikDva.stred = bodJedna;
//zobrazi pozici druheho ctverce
System.out.println("X souradnice druheho obdelniku: "
+ obdelnikDva.stred.x);
System.out.println("Y souradnice druheho obdelniku: "
+ obdelnikDva.stred.y);
//presune druhy obdelnik a zobrazi jeho novou pozici
obdelnikDva.move(40, 72);
System.out.println("X souradnice druheho obdelniku: "
+ obdelnikDva.stred.x);
System.out.println("Y souradnice druheho obdelniku: "
+ obdelnikDva.stred.y);
}
}
Tento program vytváří různé objekty, manipuluje s nimi a zobrazuje je. Zde je jeho výstup:
Sirka prvniho obdelniku: 100Vyska prvniho obdelniku: 200
Plocha prvniho obdelniku: 20000
X souradnice druheho obdelniku: 23
Y souradnice druheho obdelniku: 94
X souradnice druheho obdelniku: 40
Y souradnice druheho obdelniku: 72
Vytvoření objektů
Jak již víte, třídy vytvářejí vzor pro objekty; dle třídy poté můžete vytvořit objekt.
Každý z následujících řádků vytváří jeden objekt:
Point bodJedna = new Point(23, 94);
Rectangle obdelnikJedna = new Rectangle(bodJedna, 100, 200);
Rectangle obdelnikDva = new Rectangle(50, 100);
První řádek vytváří objekt třídy Point (bod) a další dva vytváří objekty tříd Rectangle (obdélník). Každý z těchto příkazů má tři části (o kterých se budeme dále bavit):
- Deklarace: Kódy, které jsou tučně, jsou deklarace proměnných, jež přiřazují jména proměnných odpovídajícím typům.
- Vytvoření instance: Klíčové slovo
new
je operátor Javy, který vytvoří nový objekt. - Inicializace: Operátor
new
je následován voláním konstruktoru, který inicializuje třídu.
Deklarace proměnné odkazující na objekt
V předešlých dílech, když jste deklarovali proměnnou, jste psali:
typ název;
To upozornilo kompilátor, že budete používat název pro odkazovaní na data, jejichž typ je typ. S proměnnou primitivního typu vyhradí tato deklarace potřebnou část paměti pro daný typ.
Můžete také deklarovat porměnnou referenčního typu na vlastním řádku. Například:
Point prvniBod;
Pokud jste deklarovali prvniBod
jako výše, jeho hodnota bude neurčená, dokud nebude objekt vytvořen a této proměnné přiřazen.
Jednoduchá deklarace proměnné referenčího typu nevytvoří objekt.
Pro vytvoření musíte použít operátor new
, jak je popsáno v další sekci. Tento objekt musíte do originOne
přiřadit dříve, než proměnnou ve své aplikaci použijete. Jinak získáte chybu kompilátoru.
Proměnná v tomto stavu, která momentálně neodkazuje nikam, může být znázorněna například tímto obrázkem (název proměnné, originOne
, plus odkaz nikam):
Vytvoření instance třídy
Operátor new
zjistí třídu, alokuje potřebnou paměť a vrátí odkaz na tuto paměť. Operátor new
také zavolá konstruktor třídy.
Poznámka: Fráze „instantizovat třídu“ znamená to samé jako „vytvořit objekt“. Když vytváříte objekt, vytváříte „instanci“ třídy, proto „konkretizace“ třídy.
Operátor new
požaduje jeden argument psaný za jeho názvem: volání konstruktoru. Jméno konstruktoru poskytuje operátoru i název třídy k instantizaci.
Operátor new
vrací odkaz na nově alokovanou paměť. Tento odkaz je obvykle přeřazen proměnné odpovídajícího typu:
Point prvniBod = new Point(23, 94);
Odkaz vrácený operátorem new
nemusí být nutně přiřazen proměnné. Může být také použit přímo ve výrazu. Například:
int vyska = new Rectangle().height;
Tento příkaz bude vysvětlen v příští sekci.
Inicializace objektu
Zde je kód třídy Point
(bod):
public class Point {
public int x = 0;
public int y = 0;
// konstruktor
public Point(int a, int b) {
x = a;
y = b;
}
}
Tato třída obsahuje jeden konstruktor. Konstruktor poznáte podle toho, že má stejné jméno jako třída a že nemá návratový typ. Konstruktor ve třídě Point
přebírá dva celočíselné argumenty, jak je deklarováno kódem (int a, int b)
. Náseldující příkaz poskytuje 23 a 94 jako hodnoty pro tyto argumenty:
Point bodPrvni = new Point(23, 94);
Výsledek vykonání tohoto kódu ukazuje tento obrázek:
Zde je kód třídy Rectangle
(obdélník), která obsahuje 4 konstruktory:
public class Rectangle {
public int sirka = 0;
public int vyska = 0;
public Point stred;
// čtyři konstruktory
public Rectangle() {
stred = new Point(0, 0);
}
public Rectangle(Point p) {
stred = p;
}
public Rectangle(int s, int v) {
stred = new Point(0, 0);
sirka = s;
vyska = v;
}
public Rectangle(Point p, int s, int v) {
stred = p;
sirka = s;
vyska = v;
}
// metoda pro pohyb s obdelnikem
public void move(int x, int y) {
stred.x = x;
stred.y = y;
}
// metoda pro vypocet obsahu obdelniku
public int getArea() {
return sirka * vyska;
}
}
Každý konstruktor vám umožňuje nastavit střed, výšku a šířku obdélníku, užívajíce jak primitivní typy, tak referenční. Jestliže má třída více konstruktorů, musí mít odlišné signatury. Java kompilátor odlišuje konstruktry podle počtu typu argumentů. Když se Java kompilátor setká s následujícícm kódem, ví, že má zavolat konstruktor ve třídě Rectangle
, který požaduje argument Point
následovaný dvěma celočíselnými argumenty:
Rectangle prvniObdelinik = new Rectangle(prvniBod, 100, 200);
Toto zavolá jeden z konstruktorů Rectangle
, který inicializuje stred
na prvniBod
. Dále konstruktor nastaví sirka
na 100 a vyska
na 200. Nyní jsou dva odkazy na stejný objekt Point
– objekt může mít více referncí na sebe, jak ukazuje následující obrázek.
Následující řádek kódu zavolá konstruktor třídy Rectangle
, který vyžaduje dva celočíselné argumenty, které poskytují inicializační hodnoty pro sirka
a vyska
. Jestliže si prohlédnete kód uvnitř konstruktoru, uvidíte, že vytváří nový objekt Point
, jehož hodnoty x
a y
jsou inicializovány na 0:
Rectangle druhyObdelnik = new Rectangle(50, 100);
Konstruktor Rectangle
, používaný v následujícím příkazu, nepřebírá žádné argumenty, takže je nazýván bezargumentový (bezparametrový, výchozí) konstruktor:
Rectangle rect = new Rectangle();
Užívání objektů
Jakmile vytvoříte objekt, nejspíše jej budete chtít k něčemu použít. Možná budete chtít přistupovat k hodnotám jeho atributů, změnit jeden z jeho atribut nebo zavolat jeho metody pro nějakou akci.
Přístup k atributům objektu
Atributy objektu jsou přístupné pomocí názvu, který musí být jednoznačný.
Pokud jste přímo v dané třídě, můžete pro atributy použít jednoduše její jméno. Například můžeme přidat příkaz uvnitř kódu třídy Rectangle
, který vytiskne výšku a šířku:
System.out.println("Vyska a sirka jsou: " + vyska + ", " + sirka);
V tomto případě vyska
a sirka
jsou jednoduchá jména.
Kód, který je mimo třídu objektu, musí použít referenční proměnnou nebo výraz následovaný operátorem tečka (.) a až poté jednoduchým jménem atributu jako zde:
promennaSObjektem.nazevVlastnosti
Například kód, který jsme uvedli, když jsme se začali bavit o objektech, byl mimo třídu Rectangle
. Proto při odkazování na atributy stred
, sirka
a vyska
uvnitř objektu třídy Rectangle
nazvaného obdelnikJedna
musel program použít obdelnikJedna.stred
, obdelnikJedna.sirka
a obdelnikJedna.vyska
. Následující kousek programu využívá tyto jména k vytištění sirka
a vyska
objektu vyska
:
System.out.println("Sirka prvniho obdelniku: " + obdelnikJedna.sirka);
System.out.println("Vyska prvniho obdelniku: " + obdelnikJedna.vyska);
Použití jednoduchých jmen sirka
a vyska
z kódu programu nemá žádný efekt – tyto atributy existují pouze uvnitř objektu – a vyústí v chybu při kompilaci.
Později používá program stejný kód pro zobrazení informací o obdelnikDva
. Objekty stejného typu mají svou vlastní sbírku instančních atributů. Takže každý objekt třídy Rectangle
má atributy nazvané stred
, sirka
a vyska
. Když k této instanci přistupujete přes odkaz (např. proměnnou),ukazuje na příslušnou sadu atributů. Tyto dva objekty
obdelnikJedna
a obdelnikDva
v programu z úvoní části mají odlišné atributy stred
, sirka
a vyska
.
Pro přístup k atributům můžete využít buďto referenční proměnnou, jako v minulých příkladech, nebo můžete využít výraz vracející odkaz na objekt. Zavolání operátoru new vrací odkaz na objekt. Takže můžete použít hodnotu vrácenou z operátoru k přístupu k atributům:
int vyska = new Rectangle().vyska;
Tento příkaz vytvoří objekt Rectangle a přímo přistupuje k jeho výšce. V podstatě tento příkaz vypočítá výchozí výšku objektu. Všimněme si, že jakmile se tento příkaz vykoná, program nebude mít dále odkaz na vytvořený objekt Rectangle, protože program tuto odkaz nikde neukládá. Objekt je zničen a jeho zdroje jsou pomocí Java Virtual Machine recyklovány.
Volání metod objektu
Odkaz na objekt můžete taktéž využít k volání metod. Prostě přidáte jednoduché jméno metody za odkaz na objekt, kterému předchází operátor tečka (.). Také poskytnete v kulatých závorkách potřebné argumenty, jsou-li nějaké. Jestliže metoda nevyžaduje žádné argumenty, použijete prázdné kulaté závorky.
odkazNaObjekt.nazevMetody(argumenty);
or
odkazNaObjekt.nazevMetody();
Třída Rectangle má dvě metody: getArea() pro výpočet plochy obdélníku a move() pro přesun středu obdélníku. Zde je kód z úvodní části, který volá metodu:
System.out.println("Plocha prvniho obdelniku: " + prvniObdelnik.getArea());
...
druhyObdelnik.move(40, 72);
První příkaz zavolá metodu objektu prvniObdelnik nazvanou getArea()
a zobrazí výsledky. Druhý příkaz přesune druhyObdelnik, protože metoda
move() přesune nové hodnoty atributům stred.x a stred.y.
Jako u atributů, odkazNaObjekt musí být platná odkaz na objekt. Můžete použít název proměnné nebo jakýkoli jiný výraz vracející odkaz na objekt. Operátor new vrací odkaz na objekt, takže můžete použít například následující kód:
new Rectangle(100, 50).getArea()
Výraz new Rectangle(100, 50) vrací odkaz, ukazující na objekt Rectangle.
Některé metody, jako napříkad getArea(), vracejí hodnotu. Metody vracející hodnotu můžete použít ve výrazu. Můžete hodnotu přiřadit proměnné, můžete podle hodnoty dělat rozhodnutí nebo kontrolovat smyčku. Následující kód přiřadí hodntu z metody getArea() do proměnné povrchObdelniku:
int povrchObdelniku = new Rectangle(100, 50).getArea();
Garbage Collector (česky uklízeč)
Některé objektově orientované jazyky (např. C++) po programátorech požadují, aby objekty, které již nejsou využívány, byly odstraněny. Přímá správa paměti je nudná a náchylná na chyby. Platforma Java vám umožňuje vytvořit tolik objektů, kolik chcete (počet může být samozřejmě omezen operačním systémem), a vy se nemusíte starat o jejich odstranění. Běhové prostředí Javy objekt zničí, jakmile zjistí, že již nebude dále potřeba. Tento proces je nazýván garbage collection (sběr odpadů) a stará se o něj gargabe collector (doslova přeloženo popelář).
Objekt bude zničen, jakmile nebude existovat žádný odkaz na tento objekt. Odkazy držené v proměnných jsou obvykle ztraceny, jakmile jsou proměnné mimo svůj obor platnosti. Nebo můžete explicitně odstranit odkaz, když proměnné přiřadíte speciální hodnotu null. Pamatuje, že program může mít více odkazů na stejný objekt; všechny odkazy musí být odstraněny před tím, než bude objekt zničen.
Běhové prostředí Javy má garbage collector, který periodicky recykluje objekty, na které neexistuje žádný odkaz. Garbage collector dělá tuto práci automaticky, jakmile uzná, že je vhodný čas.
V příštím díle
V příštím díle se zaměříme na více podrobností ohledně tříd, konkrétně na tato témata:
- Vracení hodnot z metod
- Použití klíčového slova this
- Kontrola přístupu k atributům
- Rozdíl mezi členy instančními a třídními
- Inicializace atributů