Třída, objekt
-
Pojmy třída, objekt
-
Deklarace a definice tříd, jejich vlastnosti (proměnné, metody)
-
Vytváření objektů, proměnné odkazující na objekt
-
Jmenné konvence — jak tvořit jména tříd, proměnných, metod
Metody, přístupy
-
Použití objektů, volání metod, přístupy k proměnným
-
Modifikátory viditelnosti (
public
,private
…) -
Konstruktory (dotvoří/naplní prázdný objekt)
-
Přetěžování metod (dvě metody se stejným názvem a jinými parametry)
Třída, objekt, jejich vlastnosti
-
Třída (také poněkud nepřesně zvaná objektový typ) představuje skupinu objektů, které nesou stejné vlastnosti,
-
"Stejné" je myšleno kvalitativně, typově, nikoli ve smyslu konkrétních hodnot — ty jsou pro různé objekty téže třídy různé.
-
Např. všechny objekty třídy
Person
mají vlastnostname
, -
tato vlastnost má však obecně pro různé lidi různé hodnoty — lidi mají různá jména.
Příklad
-
Objekt je jeden konkrétní jedinec (instance, reprezentant či entita) příslušné třídy.
-
Pro konkrétní objekt nabývají vlastnosti deklarované třídou konkrétních hodnot.
Příklad:
-
Třída
Person
má vlastnostname
-
Objekt
panProfesor
typuPerson
má vlastnostname
s hodnotouVáclav Klaus
.
Vlastnosti objektu
-
proměnné neboli atributy
-
metody
-
Vlastnosti objektů — proměnné/atributy i metody — je třeba deklarovat.
-
viz Oracle The Java™ Tutorials Lesson: Classes and Inheritance
Vlastnosti: atributy, metody
- Proměnné/atributy
-
-
jsou nositeli "pasivních" vlastností, jistých charakteristik objektů
-
de facto jde o datové hodnoty vložené (zapouzdřené, přebývající) v objektu
-
- Metody
-
-
jsou nositeli "výkonných" vlastností; "schopností" objektů
-
de facto jde o funkce/procedury pracující (převážně) nad proměnnými objektu
-
Deklarace a použití třídy
-
deklarujme třídu objektů — lidí:
public class Person { private String name; private int age; public Person(String name, int age) { // pomocí this odlišíme proměnnou objektu od parametru! this.name = name; this.age = age; } public void writeInfo() { System.out.println("Person:"); System.out.println("Name " + name); System.out.println("Age " + age); } }
Příklad použití třídy Person
Použijeme ji v programu, tzn.:
-
Vytvoříme instanci (objekt) typuPerson.
-
Vypíšeme informace o něm pomocí metody tohoto objektu.
Příklad použití třídy Person v programu
Mějme deklarovánu třídu Person
. Metoda main
v následujícím programu Demo
:
-
deklaruje dvě lokální proměnné typu
Person
— budou obsahovat odkazy na následně vytvořené objekty — lidi -
vytvoří tyto dva lidi (pomocí
new Person
) -
zavolá jejich metody
writeInfo()
Příklad použití třídy Person (dvě instance)
public class Demo { public static void main(String[] args) { Person ales = new Person("Ales Necas", 38); Person beata = new Person("Beata Novakova", 36); ales.writeInfo(); beata.writeInfo(); } }
Tedy: vypíší se informace o obou vytvořených objektech — lidech.
Nyní podrobněji k proměnným objektů.
Příklad použití třídy Person (2)
-
Ve výše uvedeném programu znamenalo na řádku:
Person ales = new Person("Ales Necas", 38);
-
Person ales
je pouze deklarace (tj. určení typu) proměnné ales - bude typu Person. -
Až
ales = new Person ("Ales Necas", 38)
je samotným vytvořením objektu osoby (Person) se jménemAles Necas
a přiřazení odkazu na něj do proměnnéales
. -
Lze napsat zvlášť do dvou řádků nebo (tak jak jsme to udělali) na řádek jeden.
-
Každý příkaz i samostatně stojící deklaraci ukončujeme středníkem.
Vytváření objektů
-
Ve výše uvedených příkladech jsme objekty vytvářeli voláním
new Person(…)
a bezděčně jsme tak použili: -
operátor
new
, který vytvoří prázdný objekt typu Person a vzápětí sám provede -
volání konstruktoru , který prázdný objekt naplní počátečními údaji (daty).
Shrnutí
-
Objekty:
-
jsou instancemi "své" třídy
-
vytváříme je operátorem
new
, kde následuje volání konstruktoru -
vytvořené objekty ukládáme do proměnné stejného typu (nebo typu předka či implementovaného rozhraní — o tom až později)
-
Pozn. Ve skutečnosti se v Javě nikdy celé objekty do proměnné neukládají, jde vždy o uložení pouze odkazu (adresy) na objekt.
-
Atributy (proměnné)
-
Terminologie: pro data zapouzdřená do objektů budeme používat záměnným způsobem označení atributy či proměnné. Je to totéž.
-
Atribut je jednoznačnější, jde vždy o datovou položku objektu či třídy, zatímco proměnné mohou být i lokální ("pomocné") uvnitř metody.
-
Položky
name
aage
v předchozím příkladu jsou atributy/proměnné objektuPerson
. Jsou deklarovány v těle deklarace třídy Person. -
Deklarace atributu/proměnné objektu má tvar: modifikátory TypProměnné jménoProměnné;
-
např.
private int age;
Datové typy primitivní
-
Výše uvedený atribut/proměnná
age
měl/a datový typ int (32bitové celé číslo). -
Tedy: proměnná takového typu nese jednu hodnotu typu celé číslo
-
Kromě celých čísel int nabízí Java celou řadu dalších primitivních datových typů (pro celá i necelá čísla, logické hodnoty, znaky).
-
Primitivní (základní, dále nedělitelné) typy jsou Javou dané napevno, programátor je nedefinuje ani nemodifikuje (na rozdíl např. od C/C++), nýbrž jen používá.
-
V Javě tedy neexistuje (na rozdíl od C/C+
) možnost typy modifikovat (např. +unsigned int
).
Datové typy objektové
-
Tam, kde nestačí jednoduché hodnoty (tj. primitivní typy), musíme použít typy složené , objektové.
-
Objektovými typy v Javě jsou třídy (
class
) a rozhraní (interface
) i pole. Třídy už jsme viděli na příkladu Person. -
Existují třídy definované přímo v Javě, v knihovně Java Core API.
-
Nenajdeme-li třídu, kterou potřebujeme, v Java Core API ani v nám dostupných a použitelných knihovnách, můžeme si ji nadefinovat sami.
Konvence pro psaní kódu
-
Konvencemi rozumíme zaužívaná doporučení, která především:
-
Usnadňují čtení cizího (i vlastního) kódu.
-
Eliminují tím chybovost.
-
Zvyšují produktivitu, šetří čas vlastní i ostatních.
-
Dodržování konvencí nehlídá překladač: i kód nedodržující konvence může být přeložitelný a funkční.
-
Hlídáme si to sami tím, že to dle konvencí vědomě píšeme a můžeme použít specializované nástroje pro kontrolu.
Konvence pro psaní kódu
-
Doporučení přímo od Sun/Oracle Code Conventions for the Java Programming Language
-
Konvence užívané knize Cay Horstmann: Big Java popsané v kompaktní formě na 99 % shodné s naším pohledem na věc.
-
Do námi užívaného prostředí BlueJ je možné doinstalovat rozšíření pro hlídání stylu kódování BlueJ Checkstyle Extension, které hlídá dvě výše uvedené skupiny konvencí.
Jmenné konvence především pro proměnné
-
týkají se jak lokálních proměnných v metodách, tak atributů
-
netýkají se statických atributů a hlavně ne konstant
-
jména proměnných začínají malým písmenem
-
nepoužíváme diakritiku (problémy s editory, přenositelností a kódováním znaků) — a to přesto, že Java ji i v identifikátorech povoluje
-
raději ani český/slovenský či jiný národní jazyk, angličtině rozumí více lidí
-
je-li to složenina více slov, pak je nespojujeme podtržítkem, ale další začne velkým písmenem (tzv. "CamelCase", v případě proměnných tedy přesněji "camelCase")
Jmenné konvence — příklady atributů
-
private int yearOfBirth;
je identifikátor se správně (vhodně) utvořeným jménem, zatímco: -
private int YearOfBirth;
není vhodný identifikátor proměnné v Javě (začíná velkým písmenem) -
private int rokNarozeni;
rovněž není vhodný identifikátor proměnné v Javě (zahraniční kolegové nebudou bez dalšího komentáře rozumět, co v té proměnné je)
Jmenné konvence — závěrem
-
Dodržování jmenných konvencí je základem psaní srozumitelných programů a bude vyžadováno, sledováno a hodnoceno v odevzdávaných úlohách i písemkách.
-
Konvence se bohužel liší od zvyklostí v příbuzných jazycích.
-
V Javě se např. nepoužívá v názvech tříd znak podtržítka — je to teoreticky možné, ale skoro nikdo tak nečiní.
-
Poměrně málo často se v názvech tříd či proměnných používají číslice. Občas ano, ale nikoli na začátku a nejspíše tam, kde jde o zvláštní konkrétní význam daného čísla, např. Counter32bit.
-
Rovněž se v názvech proměnných nepoužívá tzv. "maďarská notace", kde se připojují předpony např. dle datového typu proměnné.
Zápis přístupu k atributům
-
Atributy objektu odkazujeme pomocí "tečkové notace":
public class Demo2 { public static void main(String[] args) { // vytvoření objektu ... Person ales = new Person("Ales Necas", 38); // přístup k (čtení) jeho proměnné ... System.out.println(ales.name); // modifikace (zápis do) jeho proměnné ales.name = "Aleš Novák"; } }
V reálu ale tento obrat uvidíme zřídka, protože k proměnným v objektech raději přistupujeme pomocí metod, např. get
/ set
.
Atributy — modifikátory viditelnosti
-
Viditelnost, tzn. přímá přístupnost atributů (i metod) může být řízena uvedením tzv. modifikátorů před deklaraci prvku, viz výše:
-
public
-
viditelnost odevšad:
public class Person
-
private
-
viditelnost pouze zevnitř této třídy:
private String name;
-
-
Modifikátorů je více typů (ještě další dva), zdaleka nejběžnější jsou dva právě zmíněné:
private
apublic
.
Čtení hodnot atributů
-
Objektů (tzv. instancí ) stejného typu (tj. stejné třídy) si můžeme postupně vytvořit více:
// vytvoření prvniho objektu Person ales = new Person("Ales Necas", 38); // vytvoření druheho objektu ... Person petr = new Person("Petr Svoboda", 36); // přístup k (čtení) proměnné prvního objektu System.out.println(ales.name); // přístup k (čtení) proměnné druhého objektu System.out.println(petr.name);
-
Existují tady dva objekty, každý má své (obecně různé) hodnoty proměnných — např. jsou různá jména obou lidí.
Metody — definice, volání, návrat
-
Nad existujícími (vytvořenými) objekty můžeme volat jejich metody.
-
Metoda je podprogram (v terminologii neobjektových jazyků — funkce, procedura), který primárně pracuje s proměnnými "mateřského" objektu,
-
může mít další parametry,
-
může ve svém kódu (těle) deklarovat lokální proměnné — v našem příkladu metoda
main
deklarovala proměnnéales
,petr
.
Atribut vs. lokální proměnná
-
Pro výsledky a mezivýsledky výpočtů používáme na ukládání hodnot lokální proměnné nebo atributy objektů. Rozdíl mezi lokální proměnnou a atributem (proměnnou objektu) je značný:
-
Hodnota uložená v atribut objektu je "trvalá" ve smyslu, že přetrvává (až do přiřazení jiné) po celou dobu existence daného objektu.
-
U lokální proměnné v metodě platnost skončí (zruší se) tato proměnná ukončením dané metody.
-
Metoda může vracet hodnotu podobně jako v Pascalu funkce.
Metody — deklarace
-
Každá metoda se musí ve své třídě deklarovat.
-
Výše uvedená třída
Person
měla metodu na výpis informací o daném objektu/člověku:public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } //... zde jsou další metody }
Metody — použití
-
Výše uvedená třída
Person
měla metodu pro výpis informací o daném objektu/člověku:public class Person { private String name; private int age; //... zde patří konstruktor public void writeInfo() { System.out.println("Person:"); System.out.println("Name "+name); System.out.println("Age "+age); } }
Volání metod
-
Samotnou deklarací (napsáním kódu) metody se žádný kód neprovede.
-
Chceme-li vykonat kód metody, musíme ji zavolat.
-
Volání se realizuje (tak jako u proměnných) "tečkovou notací", viz dále.
-
Volání lze provést, jen je-li metoda z místa volání viditelná (přístupná). Přístupnost regulují podobně jako u proměnných modifikátory.
Volání metod — příklad
-
Vracíme se k prvnímu příkladu: vytvoříme dva lidi a zavoláme postupně jejich metodu writeInfo.
public class TestLidi { public static void main(String[] args) { Person ales = new Person("Ales Necas", 38); Person beata = new Person("Beata Novakova", 36); ales.writeInfo(); // volání metody objektu ales beata.writeInfo(); // volání metody objektu beata } }
-
Vytvoří se dva objekty
Person
a vypíší se informace o nich.
Návrat z metody
-
Kód metody skončí, tj. předá řízení zpět volající metodě (nebo operačnímu systému v případě startovní metody
main
), jakmile -
dokončí poslední příkaz v těle metody nebo
-
dospěje k příkazu
return
-
Metoda může při návratu vrátit hodnotu - tj. chovat se jako funkce (ve pascalském smyslu):
-
Vrácenou hodnotu musíme uvést za příkazem
return
. V tomto případě tedy nesmí return chybět! -
Typ vrácené hodnoty musíme v hlavičce metody deklarovat .
-
Nevrací-li metoda nic, pak musíme namísto typu vracené hodnoty psát
void
. -
Pozn.: I když metoda něco vrátí, my to nemusíme použít, ale je to trochu divné…
Parametry metod
-
V deklaraci metody uvádíme v její hlavičce tzv. formální parametry. Syntaxe:
-
modifikatory typVraceneHodnoty nazevMetody(seznamFormalnichParametru) { tělo (výkonný kód) metody }
-
seznamFormalnichParametru je tvaru: typParametru nazevFormalnihoParametru,…
-
Podobně jako v jiných jazycích parametr představuje v rámci metody lokální proměnnou.
-
Při volání metody jsou formální parametry nahrazeny skutečnými parametry .
Předávání skutečných parametrů metodám
- Hodnoty primitivních typů
-
tj. čísla, logické hodnoty, znaky se předávají hodnotou, tj. hodnota se nakopíruje do lokální proměnné metody.
- Hodnoty objektových typů
-
všechny ostatní (tj. vč. všech uživatelem definovaných typů) se předávají odkazem, tj. do lokální proměnné metody se nakopíruje odkaz na objekt — skutečný parametr
[ve skutečnosti se tedy parametry vždy předávají hodnotou, protože v případě objektových parametrů se předává hodnota odkazu na objekt — skutečný parametr.]
-
V Javě tedy nemáme jako programátoři moc na výběr, jak parametry předávat — to je ale spíše výhoda!
-
Příklad předávání parametrů — primitivní typy
-
Rozšiřme definici třídy Person o metodu scream s parametry:
... public void scream(int howManyTimes) { System.out.println("Kricim " + howManyTimes + "krat UAAAA!"); } ...
-
Při zavolání:
scream(10);
-
tato metoda vypíše
Kricim 10krat UAAAA!
Předávání parametrů — objektové typy (1)
-
Následující třída
Account
modeluje jednoduchý bankovní účet s možnostmi: -
přidávat na účet/odebírat z účtu
-
vypisovat zůstatek na něm
-
převádět na jiný účet
Předávání parametrů — objektové typy (2)
public class Account { private double balance; // stav (zustatek) penez uctu public void add(double amount) { balance += amount; } public void writeBalance() { System.out.println(balance); } public void transferTo(Account whereTo, double amount) { balance -= amount; whereTo.add(amount); } }
-
Metoda transferTo pracovat nejen se svým "mateřským" objektem, ale i s objektem whereTo předaným do metody… opět přes tečkovou notaci.
Předávání parametrů — příklad 2
-
Příklad použití třídy Account :
... public static void main(String[] args) { Account petrsAccount = new Account(); Account ivansAccount = new Account(); petrsAccount.add(100); ivansAccount.add(220); petrsAccount.transferTo(ivansAccount, 50); petrsAccount.writeBalance(); ivansAccount.writeBalance(); }