Dione
Z. KotalaP. Toman: Java
Predchozi (Obsah) Dalsi

11. Implementace OOP v Jav∞

11.1. Objekt

Program v Jav∞ je staticky strukturovßn na t°φdy, jejich╛ instance (objekty) za b∞hu dynamicky programu vznikajφ a zanikajφ. Objekt je nejprve vytvo°en (instanciovßn), nßsledn∞ m∙╛e b²t pou╛φvßn a nakonec je zru╣en.

11.1.1. Vytvo°enφ objektu

K vytvo°enφ objektu slou╛φ operßtor new, kter² mß syntaxi:

   new volßnφKonstruktoru
Operßtor alokuje pam∞╗ pro objekt a zavolß konstruktor (viz 11.2.3.), co╛ je specißlnφ metoda, kterß provßdφ inicializaci objektu. JmΘno konstruktoru je v╛dy shodnΘ se jmΘnem t°φdy objektu.

Priklad 11.1.
new String("ahoj");

vytvo°φ objekt t°φdy String a inicializuje ho konstruktorem s parametrem "ahoj".

Operßtor new vracφ referenci, odkazujφcφ na vytvo°en² objekt. Tato reference se p°i vytvo°enφ objektu obvykle zßrove≥ uklßdß (1) do referenΦnφ prom∞nnΘ (viz 7.2.):

Priklad 11.2.
String retezec;                 //  deklarace prom∞nnΘ
retezec = new String("ahoj");   //  p°i°azenφ reference

nebo zkrßcen∞:

String retezec = new String("ahoj");

11.1.2. Pou╛φvßnφ objektu

Pou╛φvßnφ objektu spoΦφvß ve volßnφ metod a p°φmΘ manipulaci se Φlensk²mi prom∞nn²mi. Pro p°φstup k prom∞nnΘ nebo metod∞ se pou╛φvß teΦkovß notace:

   reference.jmΘnoProm∞nnΘ
   reference.volßnφMetody

Priklad 11.3.
String retezec = new String("ahoj");    // vytvo°enφ objektu
retezec = retezec.concat("!");          // volßnφ metody
Metoda concat() vracφ nov² °et∞zec, kter² vznikne p°ipojenφm parametru na konec °et∞zce. V²sledek se p°i°adφ do prom∞nnΘ retezec.

Je mo╛nΘ pou╛φt i vφcenßsobnou p°φstupovou konstrukci:

Priklad 11.4.
int delka = retezec.trim().length();

Metoda trim() vracφ referenci na nov² °et∞zec (instanci t°φdy String), kter² vznikl z p∙vodnφho o°φznutφm prßzdn²ch znak∙. Metoda length() vracφ dΘlku °et∞zce (typ int). Prom∞nnΘ delka se tedy p°i°adφ dΘlka °et∞zce retezec po o°φznutφ metodou trim().

P°edchozφ zßpis lze p°epsat jako:

String orezanyRetezec = retezec.trim();
int delka = orezanyRetezec.length();

11.1.3. Zru╣enφ objektu

Java neumo╛≥uje p°φmΘ ru╣enφ (dealokaci) objektu. Objekt je zru╣en automaticky a╛ tehdy, neexistuje-li na n∞j reference. Jsou nap°φklad ru╣eny v╣echny objekty lokßlnφch prom∞nn²ch p°i ukonΦenφ metody. "RuΦnφ" zneplatn∞nφ reference se provede p°i°azenφm hodnoty null p°φslu╣nΘ referenΦnφ prom∞nnΘ.

Priklad 11.5.
String retezec = new String("ahoj");
retezec = null;   // zneplatn∞nφ reference -- objekt bude zru╣en 

Tento automatick² mechanismus ru╣enφ objekt∙ je znßm pod nßzvem garbage collection ("·klid smetφ"). Jeho v²hoda spoΦφvß v nemo╛nosti dealokovat ji╛ dealokovan² prostor nebo do n∞j zapisovat, co╛ b²vß v jin²ch jazycφch zdrojem mnoha nep°φjemn²ch chyb.

┌klid se provßdφ bu∩to synchronn∞, tzn. a╛ p°i nedostatku pam∞ti pro dal╣φ alokace, nebo asynchronn∞ na pozadφ, pokud to danß platforma umo╛≥uje (Unix, Windows95/NT). V programu lze o spu╣t∞nφ ·klidu po╛ßdat volßnφm metody System.gc(), nap°φklad v dob∞, kdy program neprovßdφ v²poΦty.

Je╣t∞ p°ed vlastnφm zru╣enφm objektu se zavolß metoda finalize() (2) (je-li definovßna), kde m∙╛e programßtor ulo╛it obsah prom∞nn²ch do souboru apod. Deklarace tΘto metody musφ vypadat nßsledovn∞:

   protected void finalize() throws Throwable

Pozn.: P°i ru╣enφ objektu nedochßzφ ke z°et∞zenφ volßnφ metod finalize() jako je tomu u konstruktor∙ p°i vytvß°enφ objektu (viz 11.2.3.).

11.2. T°φda

Pro ka╛d² objekt musφ b²t p°ed jeho vytvo°enφm deklarovßna t°φda, a╗ u╛ navr╛enß v programu nebo knihovnφ. Knihovnφ t°φdy jsou ulo╛eny v balφcφch (viz kap. 12.).

11.2.1. Deklarace t°φdy

Nejjednodu╣╣φ deklarace t°φdy mß syntaxi:

   class JmΘnoT°φdy {
      // t∞lo t°φdy
   }

Identifikßtor JmΘnoT°φdy slou╛φ jako objektov² typ, nap°φklad v deklaraci referenΦnφ prom∞nnΘ (viz 7.2.). V t∞le t°φdy mezi slo╛en²mi zßvorkami mohou b²t deklarace Φlensk²ch prom∞nn²ch (viz 11.2.4.) a/nebo deklarace a definice metod (viz 11.2.2.) (3) - obvykle v tomto po°adφ, ale nenφ to vy╛adovßno. V╣imn∞te si, ╛e za uzavφrajφcφ zßvorkou deklarace t°φdy nenφ st°ednφk.

Specißlnφm p°φpadem je t°φda, kterß neobsahuje metody. Ta pak slou╛φ jako klasickß datovß struktura (record v Turbo Pascalu, struct v C).

Obecnß deklarace t°φdy vypadß takto:

   [ modifikßtory ] class jmΘnoT°φdy
   [extends jmΘnoRodiΦovskΘT°φdy ]
   [implements seznamRozhranφ ] {
      // t∞lo t°φdy
   }

  • modifikßtory mohou b²t nßsledujφcφ:

    • public - oznaΦuje ve°ejnou t°φdu. Ve°ejnß t°φda je p°φstupnß i mimo balφk (viz kap. 12.), kde je deklarovßna. Nenφ-li t°φda ve°ejnß, je p°φstupnß pouze ve svΘm balφku.

    • abstract - t°φda deklarovanß s tφmto modifikßtorem je abstraktnφ a nesmφ b²t nikdy instanciovßna.

      Priklad 11.6.
      T°φda Number v balφku java.lang definuje metody pro vzßjemnou konverzi Φφseln²ch typ∙ (int na float atd.). Jejφmi potomky jsou mj. Float a Integer.

      Je z°ejmΘ, ╛e smysl majφ pouze instance t°φd Integer a Float - reßlnß a celß Φφsla - nikoliv t°φdy Number (obecnΘ "Φφslo" neexistuje). T°φda Number je proto deklarovßna jako abstraktnφ.

    • final - oznaΦuje koncovou t°φdu. Koncovß t°φda nem∙╛e b²t t°φdou rodiΦovskou (nem∙╛e mφt potomky).

    Nejsou-li uvedeny p°φslu╣nΘ modifikßtory, je t°φda implicitn∞ poklßdßna za neve°ejnou, neabstraktnφ a ne-koncovou. Zßrove≥ nelze pou╛φt modifikßtory abstract a final.

  • Za jmΘnem t°φdy m∙╛e b²t specifikovßna rodiΦovskß t°φda pomocφ klφΦovΘho slova extends (angl. roz╣i°uje). T°φda d∞dφ prom∞nnΘ a metody t°φdy rodiΦovskΘ. Nenφ-li tato Φßst uvedena, je rodiΦovskou t°φdou automaticky java.lang.Object (viz 11.5.).

  • Za klφΦov²m slovem implements nßsleduje jedno nebo vφce jmen rozhranφ (viz 11.6.), kterΘ t°φda implementuje. To mimo jinΘ znamenß, ╛e t°φda musφ obsahovat definice metod uvedenΘ v p°φslu╣nΘm rozhranφ. Je-li jmen rozhranφ vφce, jsou odd∞lena Φßrkami.

Priklad 11.7.
Deklarace ve°ejnΘ t°φdy Appletik, jejφ╛ rodiΦovskou je t°φda java.applet.Applet, a kterß implementuje rozhranφ Cloneable a Runnable (z balφku java.lang) vypadß takto:

public class Appletik extends java.applet.Applet
implements Cloneable, Runnable {
   public void run() {  // ...
   }
   // ...
}

Rozhranφ Runnable obsahuje metodu run, a proto musφ t°φda Appletik jejφ definici obsahovat. Rozhranφ Cloneable je prßzdnΘ a slou╛φ jen k identifikaci t°φdy (jejφ instance je mo╛nΘ klonovat - viz 11.5.).

11.2.2. Metody

Nejjednodu╣╣φ definice metody mß tvar:

   Nßvratov²Typ jmΘnoMetody ( parametry ) {
      // t∞lo metody
   }

  • Nßvratov²Typ musφ b²t n∞kter² datov² typ z kap. 7.. Nßvrat z metody a p°φpadnΘ p°edßnφ nßvratovΘ hodnoty zp∙sobφ p°φkaz return (viz 9.13.). Je-li nßvratov²m typem void, metoda nevracφ hodnotu.

  • jmΘnoMetody musφ b²t platn² identifikßtor. Pokud majφ v jednΘ t°φd∞ dv∞ metody shodnß jmΘna, musφ mφt odli╣n² poΦet a/nebo typ parametr∙ - tzv. p°et∞╛ovßnφ metod (overloading). P°i volßnφ p°etφ╛enΘ metody p°ekladaΦ na zßklad∞ argument∙ rozhodne, kterou volat. Dφky p°et∞╛ovßnφ nemusφ existovat r∙zn∞ pojmenovanΘ metody, jejich╛ funkce je prakticky shodnß:

    Priklad 11.8.
    Argumentem metody System.out.println(), kterß provßdφ v²pis na standardnφ v²stup, m∙╛e b²t prom∞nnß kterΘhokoliv zßkladnφho datovΘho typu nebo nic.

    System.out.println();         // od°ßdkuje
    System.out.println("ahoj");   // vypφ╣e ahoj (1)
    System.out.println(12345);    // vypφ╣e 12345 (2)
    

    Ve v╣ech p°φpadech se jednß o volßnφ jinΘ p°etφ╛enΘ metody - p°ekladaΦ se rozhoduje na zßklad∞ argument∙ - prvnφ p°φpad se li╣φ poΦtem argument∙, druhΘ dva jejich typem: (1) p°edßvß °et∞zec, (2) celΘ Φφslo.

  • Formßlnφ parametry metody:

    • Nejsou-li parametry uvedeny, jde o metodu bez parametr∙. (4)

    • Ka╛d² parametr mß tvar:

        [final] typ jmΘnoParametru
      
      Modifikßtor final, kter² lze pou╛φt a╛ od JDK1.1, znaΦφ konstantnφ hodnotu (nelze m∞nit hodnotu argumentu v metod∞).

    • V t∞le metody nelze deklarovat lokßlnφ prom∞nnou (viz 9.4.) pojmenovanou stejn∞ jako parametr.

    • Je-li parametr∙ vφce, jsou odd∞leny Φßrkami:

      Priklad 11.9.
      void metoda(int x, int y) {
         // ...
      }
      

  • Je-li jmΘno parametru stejnΘ jako jmΘno ΦlenskΘ prom∞nnΘ, dochßzφ k jejφmuzastφn∞nφ (hiding) parametrem. K explicitnφmu p°φstupu ke ΦlenskΘ prom∞nnΘ pak slou╛φ operßtor this (5) (viz tΘ╛ 11.8.), kter² vracφ referenci objektu na sebe:

    Priklad 11.10.
    class Trida {
       int x;
    
       Trida (int x) {   // zastφn∞nφ ΦlenskΘ prom∞nnΘ x parametrem
          this.x = x;    // p°i°azenφ hodnoty parametru ΦlenskΘ prom∞nnΘ x
          // ...
       }
    }
    

Obecnß deklarace metody vypadß takto:

   [ prßva ] [static] [abstract] [final] [native]
   [synchronized] Nßvratov²Typ jmΘnoMetody ( parametry )
   [throws seznamV²jimek ]

  • prßva - tato polo╛ka urΦuje p°φstupnost metody vn∞ t°φdy a pravidla pro d∞diΦnost. Metoda m∙╛e b²t bu∩ ve°ejnß (public), chrßn∞nß (protected), soukromß (private) nebo nemusφ mφt prßva specifikovßna v∙bec (default access). Vφce viz 11.3. a 11.4..

  • static - oznaΦuje statickou metodu. StatickΘ metody je mo╛nΘ narozdφl od nestatick²ch volat i tehdy, neexistuje-li ╛ßdnß instance danΘ t°φdy. Mohou v╣ak p°φmo manipulovat pouze se statick²mi (a sv²mi lokßlnφmi) prom∞nn²mi.

    Volßnφ statickΘ metody mß tvar:

       [ JmΘnoT°φdy.  ] jmΘnoMetody ( parametry );
    
    JmΘnoT°φdy se nemusφ specifikovat uvnit° t°φdy, kterß statickou metodu definuje.

    V jednΘ t°φd∞ nem∙╛e b²t definovßna shodn∞ pojmenovanß statickß i nestatickß metoda se stejn²m poΦtem a typem parametr∙ - jinak dojde k chyb∞ p°i p°ekladu.

  • abstract - metody deklarovanΘ jako abstraktnφ nemajφ v danΘ t°φd∞ t∞lo a musφ b²t definovßny a╛ potomky t°φdy. T°φda, kterß obsahuje abstraktnφ metody, nem∙╛e b²t instanciovßna a musφ b²t rovn∞╛ deklarovßna jako abstraktnφ (viz 11.2.1.).

    Priklad 11.11.
    abstract class A {
       abstract void metoda();   // deklarace abstraktnφ metody
    }
    

  • synchronized - viz 16.5.2..

  • final - oznaΦuje koncovou metodu. Koncovß metoda nesmφ b²t potomky p°ekryta.

  • native - nativnφ metody umo╛≥ujφ slouΦit programy psanΘ v Jav∞ a jin²ch jazycφch. Nap°φklad v∞t╣ina nφzko·rov≥ov²ch (6) metod z Java Core API je nativnφch. V b∞╛n²ch aplikacφch se nativnφ metody nepou╛φvajφ kv∙li jejich nep°enositelosti. V appletech se pou╛φvat nesmφ.

  • KlφΦovΘ slovo throws uvozuje jedno nebo vφce jmen t°φd v²jimek (viz kap. 13.), kterΘ m∙╛e metoda vyvolat. Je-li v²jimek vφce jsou odd∞leny Φßrkami.

    Priklad 11.12.
    Nßsledujφcφ metoda deklaruje, ╛e m∙╛e vyvolat v²jimky t°φdy ArithmeticException a SecurityException:

    void metoda() throws ArithmeticException, SecurityException {
       // ...
    }
    

Zßrov∞≥ nelze pou╛φt dvojic static abstract a final abstract.

Argumenty metod se v╛dy p°edßvajφ hodnotou - hodnotu argumentu sice m∞nit lze, ale navenek se to neprojevφ:

Priklad 11.13.
Metoda prohod() mß zam∞nit hodnoty sv²ch dvou argument∙:

void prohod(int x, int y) {
   int tmp = x; x = y; y = tmp;
}

void hop() {
   int a = 1, b = 2;
   prohod(a,b);  //  tohle nefunguje! (1)
   //  nadßle  a = 1,  b = 2
}

Po zavolßnφ metody prohod (1) se hodnoty argument∙ nezam∞nφ. Pro sprßvnou funkci je t°eba provΘst tuto ·pravu: prom∞nnΘ x, y se umφstφ do jednΘ instance t°φdy (2), na kterou se metod∞ prohod p°edß reference (3):

class XY {
   public int x, y;  // (2)
}

void prohod(XY xy) {
   int tmp = xy.x;
   xy.x = xy.y;
   xy.y = tmp;
}

void hop() {
   XY xy = new XY();  // objekt xy namφsto a, b

   xy.x = 1;
   xy.y = 2;
   prohod(xy);        // (3)
   // nynφ:  xy.x = 2,  xy.y = 1
}

11.2.3. Konstruktory

Konstruktor je specißlnφ metoda, kterß se volß pouze p°i vytvß°enφ objektu (viz 11.1.1.) a slou╛φ k jeho inicializaci. JmΘno konstruktoru musφ b²t shodnΘ se jmΘnem t°φdy, v nφ╛ je definovßn. Nßvratov² typ konstruktoru se neuvßdφ.

Pro konstruktory platφ pravidla uvedenß pro metody (viz 11.2.2.). Jejich deklarace v╣ak nesmφ obsahovat modifikßtory abstract, final, native, static a synchronized a nedochßzφ k d∞d∞nφ konstruktor∙.

Priklad 11.14.
class Bod {
   Bod() {  // konstrukor t°φdy Bod
      // ...
   }
}

Ka╛dß t°φda mß alespo≥ jeden konstruktor. Pokud ve t°φd∞ konstruktor nenφ uveden, vytvo°φ p°ekladaΦ automaticky implicitnφ konstruktor bez parametr∙ (default constructor), kter² nic neprovßdφ.

Konstruktor ka╛dΘ t°φdy musφ na zaΦßtku obsahovat volßnφ konstruktoru rodiΦovskΘ t°φdy, aby se zajistila °ßdnß inicializace zd∞d∞n²ch prom∞nn²ch (tzv. °et∞zenφ konstruktor∙). K volßnφ rodiΦovskΘho konstruktoru slou╛φ klφΦovΘ slovo super (viz tΘ╛ 11.8.):

   super( parametryKonstruktoru );

Volßnφ rodiΦovskΘho konstruktoru lze vynechat pouze v p°φpad∞, ╛e rodiΦovskß t°φda mß pouze jeden konstruktor bez parametr∙ nebo konstruktor implicitnφ - pak toto volßnφ p°ekladaΦ na zaΦßtek konstruktoru sßm doplnφ.

Volßnφ konstruktoru tΘ╛e t°φdy se provßdφ pomocφ operßtoru this (viz tΘ╛ str. 11):

Priklad 11.15.
class Trida {
   public Trida() {  
      this(0);             // volßnφ konstruktoru (*)
   }
   
   public Trida(int i) {   // (*)
      // ...
   }
}

Pozn.: Pokud je pot°eba zabrßnit instanciovßnφ danΘ t°φdy, staΦφ nadefinovat v╣echny jejφ konstruktory jako soukromΘ.

11.2.4. ╚lenskΘ prom∞nnΘ

╚lenskΘ prom∞nnΘ se deklarujφ v t∞le t°φdy - mimo t∞la metod (jinak by se jednalo o lokßlnφ prom∞nnΘ). Podle konvence se deklarace Φlensk²ch prom∞nn²ch uvßd∞jφ p°ed deklaracemi metod.

Pro ΦlenskΘ prom∞nnΘ platφ podobnß pravidla jako pro lokßlnφ prom∞nnΘ (viz 9.4.). Jejich deklarace m∙╛e navφc obsahovat nßsledujφcφ modifikßtory:

   [ prßva ] [static] [transient] [final] [volatile]
   typ jmΘnoProm∞nnΘ

  • prßva - tato polo╛ka urΦuje p°φstupnost prom∞nnΘ vn∞ t°φdy a pravidla pro d∞diΦnost. Prom∞nnß m∙╛e b²t bu∩ ve°ejnß (public), chrßn∞nß (protected) nebo soukromß (private) nebo nemusφ mφt prßva specifikovßna v∙bec (default access). Vφce viz 11.3. a 11.4..

  • static - statickß prom∞nnß existuje jen v jednom exemplß°i, kter² v╣echny objekty danΘ t°φdy (vΦetn∞ potomk∙) sdφlφ, tj. p°i vytvß°enφ instance t°φdy nenφ pro statickou prom∞nnou znovu alokovßna pam∞╗. StatickΘ prom∞nnΘ jsou p°φstupnΘ (v souladu s p°φstupov²mi prßvy) i tehdy, neexistuje-li (je╣t∞) instance t°φdy. Ke statickΘ prom∞nnΘ se p°istupuje touto konstrukcφ:
    
       JmΘnoT°φdy.jmΘnoProm∞nnΘ
    

    Priklad 11.16.
    Ve t°φd∞ Integer (z balφku java.lang) je deklarovßna konstanta MAX_VALUE obsahujφcφ nejv∞t╣φ hodnotu Φφsla typu int. Proto╛e je statickß, nenφ t°eba nejprve vytvß°et instanci tΘto t°φdy, a m∙╛e b²t ihned pou╛ita:

    int a = Integer.MAX_VALUE;
    

    JmΘno t°φdy (Integer) musφ b²t pou╛ito, jinak by p°ekladaΦ hledal definici konstanty v aktußlnφ t°φd∞.

  • transient - informuje, ╛e prom∞nnß nenφ souΦßstφ perzistentnφho stavu objektu - systΘm nebude jejφ hodnotu uchovßvat p°i zasφlßnφ objektu po sφti apod.

  • volatile - zaruΦφ, ╛e obsah prom∞nnΘ bude aktualizovßn p°i ka╛dΘm jejφm pou╛itφ (Φtenφ, p°i°azenφ) - pou╛φvß se tehdy, p°istupuje-li se v programu k prom∞nnΘ asynchronn∞ (viz kap. 16.) a p°i ka╛dΘm Φtenφ prom∞nnΘ je t°eba zφskat aktußlnφ hodnotu. Java zaruΦuje, ╛e hodnota libovolnΘ prom∞nnΘ je konzistentnφ s v²jimkou typ∙ typ∙ long a double, kterΘ by m∞ly b²t v╛dy deklarovßny s modifikßtorem volatile, je-li k nim provßd∞n asynchronnφ p°φstup. (7)

  • final - oznaΦuje konstantu. Jejφ obsah je nutno inicializovat p°i deklaraci a nesmφ se v programu m∞nit (p°ekladaΦ ohlßsφ chybu).

    Od verze JDK 1.1 je mo╛nΘ hodnotu v deklaraci nespecifikovat - konstanta nabude hodnoty po prvnφ (a jedinΘ!) inicializaci.

Priklad 11.17.
Deklarace ve°ejnΘ celoΦφselnΘ statickΘ konstanty MAX_VALUE, kterß je inicializovßna Φφslem 0x7fffffff (maximßlnφ hodnota pro typ int) vypadß takto:

public static final int MAX_VALUE = 0x7fffffff;

11.3. D∞diΦnost

T°φda-potomek se od rodiΦovskΘ t°φdy odvodφ v deklaraci pomocφ klφΦovΘho slova extends (viz 11.2.1.). Potomek od p°φmΘho rodiΦe d∞dφ, tj. p°ejφmß jako by byly znovu definovßny, v╣echny ΦlenskΘ prom∞nnΘ a metody, kterΘ: (8)

  • jsou deklarovßny jako ve°ejnΘ (public) nebo chrßn∞nΘ (protected),

  • nemajφ explicitn∞ urΦena p°φstupovß prßva a zßrove≥ se rodiΦovskß t°φda nachßzφ ve stejnΘm balφku jako potomek.

Potomek ned∞dφ ΦlenskΘ prom∞nnΘ a metody, kterΘ:

  • jsou deklarovßny jako soukromΘ (private) (9) ,

  • jsou deklarovßny v jinΘm balφku a nejsou ve°ejnΘ (public),

  • majφ v potomkovi stejnΘ jmΘno (a parametry - u metod) jako v rodiΦovskΘ t°φd∞. Tyto ΦlenskΘ prom∞nnΘ (metody) jsou p°edefinovßny - tzv. p°ekrytφ prom∞nn²ch a metod (overriding).

P°i p°ekr²vßnφ metod je mo╛nΘ p°φstupovß prßva pouze roz╣φ°it (na public nebo protected - v p°φpad∞ implicitnφch prßv). Naopak seznam (resp. typy) v²jimek deklarovan²ch pomocφ throws lze pouze z·╛it. Na zm∞ny modifikßtor∙ a ΦlenskΘ prom∞nnΘ omezenφ kladena nejsou.

K p°ekryt²m metodßm a prom∞nn²m rodiΦe se p°istupuje pomocφ operßtoru super, kter² vracφ referenci na rodiΦovskou t°φdu:

   super. JmΘno╚lenskΘProm∞nnΘ
   super. JmΘnoMetody

Priklad 11.18.
class A {
   void a() {
      // ...
   }
}

class B extends A {
   void a() {
      super.a();  // volß metodu rodiΦe: A.a
      a();        // volß sama sebe
      // ...
   }
}

11.4. P°φstupovß prßva

╚lenskΘ prom∞nnΘ a metody majφ specifikovßna p°φstupovß prßva (viz kap. 11.2.2. a 11.2.4.) urΦujφcφ okruh t°φd, kterΘ k nim majφ p°φstup. P°φstupem se rozumφ mo╛nost p°φmΘ manipulace se Φlensk²mi prom∞nn²mi a volßnφ metod.

T°φda mß p°φstup pouze k metodßm a Φlensk²m prom∞nn²m, kterΘ:

  • sama deklaruje,

  • d∞dφ (viz 11.3.),

  • jsou deklarovßny v jin²ch t°φdßch a jsou ve°ejnΘ (public),

  • jsou umφst∞ny ve t°φd∞ stejnΘho balφku (viz kap. 12.) a zßrove≥ majφ p°φstup nespecifikovßn nebo nastaven jako public Φi protected.

T°φda nemß p°φstup ke Φlensk²m prom∞nn²m a metodßm z jin²ch balφk∙, kterΘ jsou soukromΘ, chrßn∞nΘ nebo majφ nespecifikovßn p°φstup.

Priklad 11.19.
V p°φkladu 11.16. je konstanta MAX_VALUE deklarovßna jako ve°ejnß a je tedy p°φmo p°φstupnß v╣em ostatnφm t°φdßm (i mimo sv∙j balφk).

11.5. T°φda Object

T°φda Object z balφku java.lang je ko°enovou t°φdou ve stromu t°φd, tj. v╣echny t°φdy, a╗ u╛ knihovnφ nebo navr╛enΘ programßtorem, majφ spoleΦnΘho (nep°φmΘho) rodiΦe t°φdu Object.

Object definuje zßkladnφ metody, kterΘ musφ mφt ka╛d² objekt v Jav∞ - v∞t╣inu z nich pou╛φvß runtime systΘm. Jednß se nap°φklad o metody:

  • protected native clone() - vytvo°φ identick² objekt (ale nevolß konstruktor) a p°i°adφ stejnΘ hodnoty v╣em Φlensk²m prom∞nn²m. (10) Funguje pouze u t°φd, kterΘ implementujφ rozhranφ Cloneable.

  • public boolean equals(Object obj) - porovnßvß objekt s objektem obj.

  • public final Class getClass() - vracφ objekt reprezentujφcφ t°φdu v runtime systΘmu.

  • public String toString() - vracφ identifikaΦnφ °et∞zec objektu,

  • wait(), notify(), notifyAll() - viz 16.5.3..

11.6. Rozhranφ (interface)

Rozhranφ (interface) je syntaktickß struktura obsahujφcφ deklarace konstant a metod (bez implementacφ). Deklarace rozhranφ je podobnß deklaraci t°φdy:

   [public] interface jmΘnoRozhranφ
   [ extends seznamRozhranφ ] {
      // t∞lo rozhranφ
   }

  • public - oznaΦuje ve°ejnΘ rozhranφ. Ve°ejnΘ rozhranφ je p°φstupnΘ i mimo balφk (viz kap. 12.), kde je deklarovßno. Nenφ-li rozhranφ ve°ejnΘ, je p°φstupnΘ pouze ve svΘm balφku.

  • V nepovinnΘ Φßsti za klφΦov²m slovem extends (angl. roz╣i°uje) nßsleduje jedno nebo vφce jmen rozhranφ, jejich╛ konstanty a metody toto rozhranφ d∞dφ.

    Krom∞ hierarchickΘho stromu t°φd tedy v Jav∞ existuje je╣t∞ strom rozhranφ. Oproti t°φd∞ m∙╛e mφt rozhranφ vφce rodiΦ∙ - jmΘna rodiΦovsk²ch rozhranφ jsou odd∞lena Φßrkami:

    Priklad 11.20.
    Deklarace rozhranφ Slucujici, kterΘ mß dv∞ rodiΦovskß rozhranφ: Runnable a Cloneable vypadß takto:

    interface Slucujici extends Runnable, Cloneable {}
    

T∞lo rozhranφ smφ obsahovat pouze deklarace konstant a metod. P°i tom platφ nßsledujφcφ pravidla:

  • V╣echny metody a konstanty uvedenΘ v deklaraci rozhranφ jsou automaticky ve°ejnΘ (public) a nesmφ mφt specifikovßna p°φstupovß prßva protected ani private.

  • V╣echny metody jsou navφc automaticky abstraktnφ.

  • I kdy╛ u prom∞nnΘ nenφ modifikßtor final, jednß se v╛dy o konstantu.

  • V rozhranφ nesmφ b²t pou╛ity modifikßtory: transient, volatile a synchronized.

Priklad 11.21.
public interface NoveRozhranφ {
   int MAX_DELKA_RETEZCE = 20;   // automaticky konstanta
   void vypis(String retezec);   // automaticky abstraktnφ metoda
}

Rozhranφ se pou╛φvajφ k zachycenφ spoleΦn²ch prvk∙ t°φd, kterΘ spolu nemusφ souviset ve stromu d∞diΦnosti - spoleΦn²mi prvky jsou konstanty a metody deklarovanΘ rozhranφm. T°φda, kterß implementuje danΘ rozhranφ (viz 11.2.), musφ obsahovat definice v╣ech(!) metod tohoto rozhranφ. Rozhranφ pak lze pou╛φt jako objektov² typ t°φdy:

Priklad 11.22.
Program bude obsahovat schrßnku (clipboard), p°es kterou lze kopφrovat, a vklßdat objekty (text, obrßzky, zvuky). V╣echny objekty, kterΘ lze do schrßnky umφstit, musφ kopφrovßnφ samy umo╛≥ovat - musφ obsahovat metodu copy().

Z hlediska nßvrhu nenφ vhodnΘ, aby t°φdy takto rozdφln²ch objekt∙ m∞ly spoleΦnΘho rodiΦe - t°φdu, deklarujφcφ metodu copy(), kterou v╣echny povinn∞ zd∞dφ. V²hodn∞j╣φ je deklarovat rozhranφ (Clip) obsahujφcφ metodu copy(), kterΘ budou jednotlivΘ t°φdy implementovat - i v tomto p°φpad∞ bude zaruΦena podpora kopφrovßnφ ze strany objekt∙.

public interface Clip {
   byte[] copy();
}

Metoda copy() bude vracet pole byt∙ reprezentujφcφ objekt ve schrßnce. Ka╛dß t°φda, jejφ╛ instance lze kopφrovat p°es schrßnku, musφ implementovat rozhranφ Clip. Jejφ deklarace bude:

class Obrazek implements Clip {
   byte[] copy() {
      // ...
   }
}

Schrßnka pak m∙╛e obsahovat libovoln² objekt typu Clip:

class Schranka {
   byte[] schranka;

   // metoda pro vlo╛enφ (kopφrovatelnΘho) objektu
   public void vlozit(Clip objekt) {   // typ parametru je rozhranφ
      schranka = objekt.copy();        // vlo╛enφ objektu do schrßnky
   }
   // ...
}

Rozhranφ m∙╛e b²t prßzdnΘ. T°φdu implementujφcφ rozhranφ lze identifikovat operßtorem instanceof, viz 8.2..

Pozn.: Rozhranφ neumo╛≥ujφ vφcenßsobnou d∞diΦnost, nebo╗ t°φdy prost°ednictvφm rozhranφ ned∞dφ definice (k≤d) metod. Hierarchie rozhranφ je nezßvislß na hierarchii t°φd.

11.7. Inicializace t°φd a rozhranφ

K inicializaci t°φdy nebo rozhranφ dochßzφ p°i prvnφm aktivnφm pou╛itφ, kterΘ nastane, je-li spln∞na aspo≥ jedna z podmφnek (11) :

  • je vyvolßna metoda nebo konstruktor deklarovan² danou t°φdou.

  • je vytvo°eno pole s prvky typu danΘ t°φdy,

  • je proveden p°φstup k nekonstantnφ ΦlenskΘ prom∞nnΘ t°φdy nebo konstant∞ rozhranφ,

  • je proveden p°φstup ke ΦlenskΘ prom∞nnΘ t°φdy s modifikßtorem final nebo static, kterß je inicializovßna hodnotou vypoΦφtanou za b∞hu programu.

Inicializace t°φdy se sklßdß z inicializace statick²ch Φlensk²ch prom∞nn²ch a vykonßnφ statick²ch inicializßtor∙ (viz dßle), p°iΦem╛ p°ed tφm musφ b²t inicializovßna nejprve jejφ rodiΦovskß t°φda.

Inicializace rozhranφ spoΦφvß pouze v inicializaci v n∞m definovan²ch konstant, nedochßzφ automaticky k inicializaci rodiΦovskΘho rozhranφ.

11.7.1. Inicalizßtory

Od JDK 1.1 lze k inicializaci t°φdy (resp. instance) pou╛φt statick² (resp. nestatick²) inicializßtor. Jeho syntaxe je:

 deklaraceT°φdy {
   [static] {
      // inicializace
   }
}

Jednß se o blok, kter² obsahuje inicializace Φlensk²ch prom∞nn²ch. Statick² inicializßtor vyvolßvß pouze t°φda. Nestatick² inicializßtor vyvolßvajφ v╣echny konstruktory t°φdy. Nestatick² inicializßtor smφ vyvolßvat pouze v²jimky, kterΘ deklarujφ v╣echny konstruktory t°φdy. (12) .

Priklad 11.23.
class A {
   static {
      String ahoj = "ahoj";
   }
   // ...
}

11.8. Vno°enΘ t°φdy

Od verze JDK 1.1 je mo╛nΘ t°φdy do sebe vno°ovat (13) a Java rozeznßvß dva druhy t°φd:

  • T°φdy nejvy╣╣φ ·rovn∞ (top-level classes) - jsou "normßlnφ" t°φdy a statickΘ t°φdy (14) umφst∞nΘ v jinΘ t°φd∞ (na ·rovni vno°enφ nezßle╛φ). Do tΘto skupiny se takΘ °adφ takΘ vno°enß rozhranφ.

    Priklad 11.24.
    Ob∞ nßsledujφcφ t°φdy TopLevel1 a TopLevel2 jsou t°φdy nejvy╣╣φ ·rovn∞.

       class TopLevel1 {
          static class TopLevel2 {
             // ...
          }
    
          interface Cool {
             // i rozhranφ m∙╛e b²t vno°enΘ
          }
       }
    

    T°φdy nejvy╣╣φ ·rovn∞ mohou b²t zp°φstupn∞ny (zßvisφ na p°φstupov²ch prßvech) udßnφm ·plnΘho jmΘna t°φdy. Podobn∞ jako u balφk∙ (viz kap. 12.) se pou╛φvß teΦkovß notace: TopLevel1.TopLevel2 je ·plnΘ jmΘno vno°enΘ t°φdy TopLevel2.

    T°φdy nejvy╣╣φ ·rovn∞ umo╛≥ujφ vytvß°et hierarchickou strukturu na ·rovni t°φd, nikoliv pouze na ·rovni balφk∙.

  • Vnit°nφ t°φdy (inner classes) - jsou nestatickΘ vno°enΘ t°φdy a lze je umφstit i do t∞la metody nebo do bloku. Vnit°nφ t°φdy definovanΘ v bloku nebo metod∞ nejsou "zvenku" p°φstupnΘ a nemohou mφt modifikßtory public, protected, private a static. Vnit°nφ t°φdy nesmφ obsahovat statickΘ prom∞nnΘ a metody, statickΘ inicializßtory, ani deklarace rozhranφ.

    Vnit°nφ t°φdy jsou obecn∞j╣φm nßstrojem pro p°φpady, kdy jinΘ jazyky pou╛φvajφ ukazatele na funkce.

    Zvlß╣tnφm druhem vnit°nφ t°φdy je nepojmenovanß, anonymnφ t°φda (anonymous class). Deklarace anonymnφ t°φdy je souΦßstφ roz╣φ°enΘ syntaxe operßtoru new:

       new Typ ( parametry ) {
          // t∞lo anonymnφ t°φdy
       }
    

    Typ p°edstavuje:

    • jmΘno konstruktoru rodiΦovskΘ(!) t°φdy, od kterΘ je anonymnφ t°φda odvozena (nßsledujφ jeho parametry), nebo

    • jmΘno rozhranφ - anonymnφ t°φda jako jedinß m∙╛e p°φmo instanciovat rozhranφ (zde se parametry neuvßdφ). (15)

    Priklad 11.25.
    Vytvo°enφ ΦlenskΘ prom∞nnΘ r jako instance rozhranφ Runnable (viz tΘ╛ 16.2.) vypadß nßsledovn∞:

    class NejakaTrida {
       Runnable r = new Runnable() {
          public void run() {
             // ...
          }
       }
    }
    

Vnit°nφ t°φdy majφ p°φm² p°φstup k soukrom²m statick²m prom∞nn²m a metodßm vn∞j╣φ t°φdy a nemusφ pou╛φvat jejich ·plnß jmΘna. T°φdy nejvy╣╣φ ·rovn∞ mohou manipulovat pouze se statick²mi prom∞nn²mi a statick²mi metodami vn∞j╣φch t°φd.

Pokud vnit°nφ t°φda ve sv²ch metodßch pou╛φvß lokßlnφ prom∞nnΘ nebo parametry, kterΘ sama nedeklaruje, musφ tyto b²t deklarovßny s modifikßtorem final.

Proto╛e po zavedenφ vnit°nφch t°φd v JDK 1.1 m∙╛e mφt danß t°φda vφce instancφ, je v n∞kter²ch p°φpadech pou╛itφ operßtor∙ new a super nutno explicitn∞ uvΘst referenci na instanci vn∞j╣φ t°φdy: (16)


   referenceNaVn∞j╣φInstanci. new
   referenceNaVn∞j╣φInstanci. super

Podobn∞ byla roz╣φ°ena syntaxe operßtoru this, kde je mo╛nΘ specifikovat vn∞j╣φ t°φdu:


   JmΘnoVn∞j╣φT°φdy. this

Priklad 11.26.
class Vnejsi {
   static int i = 10;                    // (1)
   int x;

   class Vnitrni {
      Vnitrni() {
         int i = 0;                      // (2)
         int j = Vnejsi.this.i;          // (3)
         // ...
      }
   }

   static Vnitrni delej(Vnejsi obj) {
      // ...
      return obj.new Vnitrni();          // (4)
   }
}

Na °ßdce (3) je prom∞nnΘ j p°i°azen obsah statickΘ prom∞nnΘ i (1) - v p°φpad∞ neuvedenφ t°φdy by se p°i°adila hodnota prom∞nnΘ i (2).

Na °ßdce (4) je nutnΘ u operßtoru new uvΘst referenci na instanci obj, nebo╗ metoda delej() je statickß a jako takovß nem∙╛e (automaticky) p°edat konstruktoru referenci na instanci vn∞j╣φ t°φdy.


  • (1) Objekt, na n∞j╛ neodkazuje ╛ßdnß referenΦnφ prom∞nnß, je automaticky zru╣en (viz 11.1.3.).
  • (2) V jin²ch jazycφch mß podobnou funkci tzv. destruktor.
  • (3) Od JDK 1.1 m∙╛e t°φda obsahovat dal╣φ t°φdy, viz 11.8..
  • (4) Narozdφl od jazyka C, kde u bezparametrickΘ funkce ANSI norma vy╛aduje uvedenφ typu void v mφst∞ parametru.
  • (5) V Turbo Pascalu mß ekvivalent self.
  • (6) Jednß se p°evß╛n∞ o metody, kterΘ jsou zßvislΘ na hardwaru nebo na operaΦnφm systΘmu (nap°. metody pro Φtenφ ze souboru).
  • (7) D∙vodem je, ╛e 64-bitovΘ operace jsou v n∞kter²ch implementacφch provßd∞ny po 32 bitech.
  • (8) StatickΘ prom∞nnΘ a metody potomek s rodiΦovskou t°φdou sdφlφ.
  • (9) P°φstup ze zd∞d∞n²ch metod ov╣em z∙stßvß zachovßn.
  • (10) Pro ΦlenskΘ prom∞nnΘ typu objekt clone() neprovßdφ! Proto je t°eba dßt pozor u vφcerozm∞rn²ch polφ - nekopφrujφ se vy╣╣φ indexy, ale pouze se p°i°adφ.
  • (11) Podrobn² popis inicializacφ i s ohledem na synchronizaci obsahuje [GJS96].
  • (12) To neplatφ pouze pro anonymnφ t°φdy, viz 11.8..
  • (13) Toto roz╣φ°enφ je v╣ak binßrn∞ kompatibilnφ s JDK 1.0 - p°ekladaΦ provßdφ transformace na ·rovni zdrojovΘho textu.
  • (14) U t∞chto t°φd lze na rozdφl od doposud znßm²ch ·rovn∞ pou╛φt modifikßtor static.
  • (15) Ve skuteΦnosti bude tato t°φda potomkem t°φdy java.lang.Object, kter² p°φslu╣nΘ rozhranφ implementuje.
  • (16) D∙vodem je, ╛e k instanci vn∞j╣φ t°φdy m∙╛e existovat zßrove≥ n∞kolik instancφ t°φd vnit°nφch a vnit°nφ t°φdy majφ p°φstup ke Φlensk²m prom∞nn²m t°φdy vn∞j╣φ.

Predchozi
Converted by Selathco v0.9 on 25.09.1999 19:46
Dalsi