Počítače a programování 1 6.přednáška
Deklarace tříd a objektů Vytváření objektů Objekty a reference Třídy a objekty Deklarace tříd a objektů Vytváření objektů Objekty a reference
Úvod Základní předpoklad jazyku Java: Chceme ji používat k objektově orientovanému programování V Javě je vše považováno za objekt, dokonce i program v Javě Každý programovací jazyk obsahuje vlastní prostředky určené k manipulaci s daty Programátor si musí systematicky uvědomovat, o jaký typ manipulace se právě jedná – zda se bude s objektem manipulovat přímo či prostřednictvím určitého typu nepřímého vyjádření Java – jednodušší – vše je považováno za objekt, identifikátor je ve skutečnosti odkazem na příslušný objekt
Úvod Co stanovuje typ objektu? Vytváření nových datových typů: třída Většina objektově orientovaných jazyků používá klíčové slovo class Třída (Class) — je základním stavebním kamenem v objektově orientovaném jazyce
Třída (class) – základní pojmy Třída (objektový typ) je jakási šablona (nemá přidělenou žádnou paměť). Při návrhu definice nové třídy lze do třídy vložit dva typy prvků: datové členy (též nazývané pole nebo položky), členské funkce (zpravidla nazývané metodami).
Třída (class) – základní pojmy Třída se v skutečnosti skládá: ze souboru proměnných (členské proměnné, datové složky, atributy), podprogramů (metod), které manipulují s členskými proměnnými (daty) . Členské proměnné (atributy) - reprezentují stav objektu – jsou v nich uloženy informace o objektu Metody – manipulují s členskými proměnnými a obecně mění stav objektu
Objekty – základní pojmy Objekt (object) – je datový prvek, který je vytvořen podle vzoru třídy (tzv. instance třídy). Podle jednoho vzoru třídy je možné vytvořit libovolné množství objektů
Příklad třídy a objektů First Instantiation: Object name: patsCar amount of fuel: 10 gallons speed: 55 miles per hour license plate: “135 XJK” Objekty, které jsou instancí třídy Deklarace třídy Second Instantiation: Object name: suesCar amount of fuel: 14 gallons speed: 0 miles per hour license plate: “SUES CAR” Class Name: Automobile Data: amount of fuel ________ speed ________ license plate ________ Methods (actions): increaseSpeed: How: Press on gas pedal. stop: How: Press on brake pedal. Third Instantiation: Object name: ronsCar amount of fuel: 2 gallons speed: 75 miles per hour license plate: “351 WLF”
Deklarace třídy Program v Javě obsahuje vždy alespoň jednu třídu specifikátor class jmeno { deklarace členských proměnných ….. deklarace metod třídy }
Deklarace třídy Specifikátor určuje přístupová práva k atributům a metodám třídy. Je-li použit specifikátor public znamená to, že proměnné i metody jsou volně přístupné komukoliv. Pozor !!! každá public třída musí být uložena v samostatném souboru. Metoda main()nemusí být součástí každé třídy – pokud ji neuvedeme, nic se nestane.
Soubory tříd Každá třída definovaná v Javě musí být v samostatném souboru. Soubor má stejné jméno jako třída, ke jménu souboru je připojena přípona ".java" Dobré programátorské doporučení: První písmeno ve jménu třídy (tedy i souboru) je velké, následují malá písmena MyClass.java pro třídu MyClass Všechny třídy, které potřebujete pro spuštění programu, uložte do stejného adresáře.
Deklarace třídy Po deklaraci se třída stává univerzálním vzorem. Pomocí tohoto vzoru a klíčového slova new lze vytvořit objekty. Nejsou-li objekty dané třídy vytvořeny, je třída bezvýznamná.
Příklad public class Obdelnik { /* – třída, která reprezentuje obdélníky */ public int sirka; public int vyska; public int obvod() { int pom; pom=2 * (sirka + vyska); return pom; } Public int obsah() { return (sirka*vyska);
Vytvoření objektu Syntax: Vytvoření objektu provází dvě akce: class_Name instance_Name = new class_Name(); Vytvoření objektu provází dvě akce: Deklarace referenční proměnné příslušného typu (v předchozím příkladu Obdelnik), která v sobě bude uchovávat referenci na skutečný objekt (instanci) – bude na něj odkazovat. Dynamické vytvoření instance (objekt) třídy pomocí new.
Vytvoření objektu Příklad: Obdelnik obd; /* ted je deklarovana referencni promenna, ale zadny objekt, nelze pouzit ani metody, ani promenne*/ obd = new Obdelnik(); /* ted se dynamicky vytvorila instance (objekt) tridy Obdelnik přes referencni promennou lze pouzit metody i promenne (jsou implicitne nastaveny na nulu)*/
Vytvoření objektu proměnná instance Pokud se v deklaraci proměnných nevyskytuje klíčové slovo static, jedná se o proměnné instance . Proměnné vznikají až na základě použití new – každá instance této třídy má své vlastní proměnné. Proměnné patří ke konkrétní instanci - instanční proměnné . Stejná pravidla platí i pro metody uvedené v proměnné instanci, nedají se použít samostatně (jako statické), jejich použití je vázáno na konkrétní instanci.
Přímý přístup k datům objektu Hodnoty proměnných konkrétní instance lze samozřejmě měnit, k označení je používána tečková notace. Jmeno_ref_promen.jmeno_promen_instance = “hodnota”; Příklad: obd.vyska = 2; obd.sirka = 9; Pozor: Nepříliš bezpečná manipulace, je-li použit specifikátor public znamená to, že proměnné i metody jsou volně přístupné komukoliv.
Metody Pro přístup k metodám je používán stejný způsob zápisu jako pro přístup k datům. Identifikator_promen = Jmeno_ref_promen.jmeno_metody(); Příklad: i= obd.obvod(); Metodě není předáván žádný parametr, přesto je zápis a následný chod programu správný – metoda pracuje implicitně nad daty své instance (upřesnění, která je to instance, určuje referenční proměnná).
Metody a Třídy Konvence jmen Dobré programátorské návyky Užívejte slovesa pro názvy void metod Provádějí akci Užívejte podstatná jména pro názvy metod, které vracejí hodnotu Vytvářejí (vracejí) část dat, konkrétní hodnotu Začínejte jména tříd velkými písmeny. Začínejte jména metod malými písmeny.
Klíčové slovo this Klíčové slovo this má speciální význam pro objekty. Je to rezervované slovo, tj. nesmí být použito jako identifikátor proměnné, třídy nebo metody Ostatní rezervovaná slova int, char, main, etc. this v sobě skrývá jméno právě volaného objektu (každá metoda má v sobě skrytý tento implicitní parametr (nemusí být nikde deklarován), který odkazuje na tuto instanci. Java umožňuje použití parametru this: Pokud metoda přistupuje pouze k svým datům, není potřeba tento parametr využívat, přesto jej však někdy uvádíme (viz pozdější výklad).
Příklad použití this Příkladem může být void metoda, která v sobě navíc obsahuje klíčové slovo this: public void writeOutput() { System.out.println("Name = " + this.name); System.out.println("Population = " + this.population); System.out.println("Growth rate = " + this.growthRate + "%"); }
Příklad použití this this referuje jméno objektu, který následně aktivuje writeOutput metodu
Vytvoření nového objektu - prakticky Kam se vlastně zapíší příkazy pro vytvoření nového objektu? Řešení: zápis do metody main, která je součástí dané třídy, nebo je možné vytvořit objekt v kterékoliv jiné třídě.
Příklad public class Obdelnik { /* – třída, která reprezentuje obdélníky */ public int sirka; public int vyska; public int obvod() { int pom; pom=2 * (sirka + vyska); return pom; } public int obsah() { return (sirka*vyska);
Public static void main(String[] args){ Obdelnik obd = new Obdelnik(); obd.vyska = 2; obd.sirka = 9; System.out.println („Obvod je:“+obd.obvod()); } Vypíše se: Obvod je: 22
Konstruktor Constructor Vytváření nových objektů: Deklarace s inicializací (viz předchozí příklad) Inicializace datových prvků objektu (popř. dalších akcí) voláním specializované metody konstruktor Konstruktor má vždy stejné jméno jako je jméno třídy Konstruktor je metoda, která nemá žádnou návratovou adresu, ale může mít libovolný počet parametrů i různých typů
public class Obdelnik { /* – třída, která reprezentuje obdélníky */ public int sirka; public int vyska; public Obdelnik (int parSirka, int ParVyska) { sirka = parSirka; vyska = parVyska; } /*ostatní deklarace metod se nemění */
Public static void main(String[] args){ Obdelnik obd = new Obdelnik(2,9); System.out.println („Obvod je:“+obd.obvod()); }
Doporučené použití Public static void main(String[] args){ Obdelnik obd = new Obdelnik(2,9); System.out.println („Obdélník výšky:“+obd.vyska+ „Obdélník šířky:“+obd.sirka+ „má obvod:“+obd.obvod()); }
Přetížení konstruktorů Konstruktor je speciální metoda navržená k inicializaci proměnných instance Je automaticky volána, když je objekt vytvářen pomocí new Má stejné jméno jako třída Přetížení konstruktoru (více než jeden konstruktor pro stejnou definici třídy) – možnost inicializace vznikající objekt různými způsoby Různé verze inicializace všech, některých, nebo žádných proměnných instance Každý konstruktor má odlišný typ (různý počet nebo pořadí parametrů)
Definování konstruktorů Hlavička konstruktorů neobsahuje slovo void Ve skutečnosti neobsahuje ani návratový typ Konstruktor bez parametrů je default constructor Jestliže není poskytnut žádný konstruktor, Java vytváří automaticky default constructor Jestliže je poskytnut jakýkoliv konstruktor, pak žádný konstruktor není vytvářen automaticky Programátorský tip Vložte konstruktor, který inicializuje všechny instanční proměnné Vložte konstruktor, který nemá žádné parametry Vložte svůj vlastní default constructor
public class Obdelnik { /* – třída, která reprezentuje obdélníky */ public int sirka; public int vyska; public Obdelnik (int Sirka, int Vyska) { this.sirka = Sirka; this.vyska = Vyska; }
// tri ruzne konstruktory public Obdelnik (int sirka, int vyska) { this.sirka = sirka; this.vyska = vyska; } public Obdelnik (Obdelnik o) { sirka = o.sirka; //this neni nutne this.vyska = o.vyska;//zlepsi se citelnost public Obdelnik () { sirka = 1; vyska = 1;
public int obvod() { int pom; pom=2 * (sirka + vyska); return pom; } Public int obsah() { return (sirka*vyska);
// pouziti Public static void main(String[] args){ Obdelnik obd = new Obdelnik(2,9); Obdelnik dalsi = new Obdelnik(obd); Obdelnik jednotk = new Obdelnik(); System.out.println („Obvod je:“+obd.obvod()); System.out.println („Obvod je:“+dalsi.obvod()); („Obvod je:“+jednot.obvod()); } Výsledky:Obvod je: 18; Obvod je: 18; Obvod je: 4;
this – přístup ke konstruktoru Speciální využití v přetížených konstruktorech Pomocí this() může konstruktor vyvolat konstruktor vyvolat jiný konstruktor téže třídy Volání this() se vythahuje na konstruktor, který má stejné parametry (shodují se do počtu i pořadí) Upozornění: volání pomocí this() musí být první příkaz ve volajícím konstruktoru
// pouziti – prepis dalsich konstruktoru jako volani jiz popsaneho konstruktoru public Obdelnik (int sirka, int vyska) { this.sirka = sirka; this.vyska = vyska; } public Obdelnik (Obdelnik o) { this(o.sirka,o.vyska); public Obdelnik () { this(1,1);
Volání metod jinými metodami Metody instance mohou volat jiné metody instancí z dané třídy – důvod: metody jedné třídy jsou si rovny a neexistuje mezi nimi žádný vztah podřízenosti či nadřízenosti Konstruktor třídy může vyvolat všechny metody téže třídy a může vyvolat i všechny konstruktory téže třídy Metodě je dovoleno zavolat konstruktor pouze prostřednictvím operátoru new
//volani metody teze tridy konstruktorem public void nastavSirku (int sirka) { this.sirka = sirka; } public Obdelnik (int sirka, int vyska) { nastavSirku(sirka); this.vyska = vyska;
Objekt a proměnná třídy Ve třídě je možno deklarovat proměnnou uvozenou klíčovým slovem static Proměnná deklarovaná uvedeným způsobem nebude duplikována v instancích této třídy – bude patřit pouze této třídě – v programu existuje pouze v jedné kopii (jedná se vlastně o „globální“ proměnnou této třídy) Proměnná se nazývá proměnná třídy (na rozdíl od proměnné instance)
Objekt a proměnná třídy Tato proměnná je využitelná i případě, pokud třída nemá žádné instance (nebyly dosud vytvořeny žádné objekty pomocí operátoru new K proměnné třídy lze také přistoupit pomocí klíčového slova this, ale nedoporučuje se – vhodnější je přístup pomocí jména třídy
Inicializace proměnných třídy Proměnné instance lze inicializovat pomocí konstruktoru – v případě proměnných třídy nevhodné (při každém novém objektu by se opět inicializovaly) Řešení: Inicializace se provede přímo v deklaraci Je-li nutno inicializovat např. pole konstant – použijeme statický inicializační blok (static initialization block)
public class Prvocisla { public static final int MAX = 1000; public static final int cisla[] = new int[MAX]; static { int pocet = 2; cisla[0] = 1; cisla[1] = 2;
for (int i = 3; pocet < MAX; i+= 2) { dalsi: for (int i = 3; pocet < MAX; i+= 2) { for (int j = 2; j < pocet; j++) { if (i % cisla[j] == 0) { continue dalsi; } cisla[pocet] = i; pocet++; // konec statickeho inicializacniho bloku
Public static void main(String[] args){ System.out.println (“Prvnich “+ MAX + ”prvocisel”); for (int i = 0; i < Prvocisla.cisla.length; i++) (cisla[i] + “ ”); } // konstanty nemusi mit prirazenou hodnotu pri deklaraci // lze ji priradit kdekoliv, ale pouze jednou
Rušení objektů - čistič paměti garbage collector Je-li objekt nepotřebný – neexistuje na něj žádný odkaz z existujících referenčních proměnných Zajištění neplatnosti odkazu: Do referenční proměnné se přiřadí odkaz na jiný objekt Nebo Referenční proměnná se přímo „vynuluje“
Rušení objektů - čistič paměti garbage collector garbage collector běží na pozadí programu s nízkou prioritou Omezí program pouze v případě nutnosti: Dojde k nedostatku paměti a je nutno uvolnit nepotřebné části. garbage collector je přímo volán příkazem System.gc(); - velmi neobvyklý případ
Ukončení práce s objekty finalizer Finalizer je metoda instance (nesmí být static), která vrací void Má vyhrazené jméno finalize()a nemá žádné parametry Musí být pouze jeden (nelze přetěžovat) Tvar hlavičky: protected void finalize() throws Trouwable { Poslední příkaz: super.finalize() Poznámka: použití má význam pouze v případě, má-li objekt ještě jiné zdroje než přidělenou paměť
Závěr Doporučení: Inicializujte proměnné instance v konstruktoru, nikoliv v deklaraci Dodržujte při deklaraci třídy následující pořadí: Proměnné Konstanty Metody