Referencie a konštruktory

<< Debugovanie programov | Obsah | Typ char a znakové reťazce >>

Pri našom programovaní doposiaľ sme sa stretli s 2 typmi premenných. Prvým typom boli premenné primitívneho typu (int, double, boolean, ...), ktoré uchovávali jednoduchú hodnotu. Druhým typom premenných boli premenné, prostredníctvom ktorých sme komunikovali s vytvorenými objektami vo "svete objektov" (napr. s kresliacou plochou, korytnačkou, či ObjectInspectorom). O týchto premenných sme si povedali, že referencujú objekty. V Jave už viac typov premenných nejestvuje.

V Jave existujú 2 typy premenných (a tiež parametrov a návratových hodnôt):

  • premenné primitívneho typu
    • int, byte, short, long, double, float, boolean a char
    • ich úlohou je uchovávať jednoduchú hodnotu
  • premenné referenčného typu
    • ich úlohou je uchovávať referenciu na objekt (vo "svete objektov")

Referenciu na objekt si môžeme predstaviť ako akúsi "šípku na objekt", či "adresu" miesta, kde objekt "býva". Ďalšou metaforou pre referenciu je metafora rodného čísla. Pre premenné referenčného typu platia všetky pravidlá, ako pre premenné primitívneho typu (práca s neinicializovanou premennou, priradenie, ...).

Premenná referenčného typu nemôže referencovať hocijaké objekty, môže referencovať iba objekty určitej triedy. Premennú refPremenna, ktorá môže referencovať objekty nejakej triedy Trieda deklarujeme tak, že najprv napíšeme názov triedy (v našom prípade Trieda), potom medzeru a nakoniec pridáme názov premennej. To všetko ukončíme bodkočiarkou:

Trieda refPremenna;

Takto vytvorená premenná je neinicializovaná. Do premennej referenčného typu môžeme uložiť:

  • referenciu na objekt (vhodnej triedy)
  • špeciálnu hodnotu null, ktorá hovorí, že daná premenná nereferencuje žiaden objekt

Ako si predstaviť abstraktný pojem referencia? Každý človek na Slovensku je jednoznačne identifikovaný svojim rodným číslom. Rodné číslo je jedinečným identifikátorom každého človeka, ktorý sa narodil na Slovensku. Podobne si referenciu na objekt môžeme predstaviť ako rodné číslo objektu, ktoré dostáva objekt, keď sa vytvorí vo svete objektov (pomocou new). Teda, ak máme premennú k deklarovanú ako Turtle k, tak premenná k je schopná uchovávať jedno rodné číslo nejakého korytnačieho objektu alebo hodnotu null. Ak píšeme k.step(100), tak hovoríme, aby objekt, ktorého rodné číslo je uložené v premennej k, vykonal metódu step s parametrom 100.

Veľmi často sa môžeme v programoch stretnúť s takouto podmienkou, ktorá testuje, či premenná naozaj referencuje nejaký objekt:

if (refPremenna != null) {
        // volanie metod referencovaneho objektu
}

Takýto test je dôležitý, ak nemáme informácie o hodnote v premennej. Ak je v nej totiž uložená hodnota null, tak premenná nereferencuje žiaden objekt. To má za následok to, že ak pomocou takejto premennej (obsahujúcej null) skúsime zavolať nejakú metódu objektu (komunikovať s objektom), program skončí s chybovou hláškou.

Ďalším typickým testom je test, či 2 premenné referenčného typu, ktoré referencujú objekty rovnakej triedy, referencujú ten istý objekt:

if (refPremenna1 == refPremenna2) {
       // ...
}

Pozrime sa na pár komentovaných ukážok priradení referenčných hodnôt:

Turtle k1;
Turtle k2;
WinPane p;

...

// Po priradení bude premenná k1 referencovať ten istý objekt, ako premenná k2
k1 = k2;
// Premenná k1 nebude referencovať žiaden objekt
k1 = null;
// Takéto priradenie je nekorektné, keďže k1 referencuje objekty triedy Turtle, kým p objekty triedy WinPane
p = k1;

Konštruktory - použitie

Referencie na objekty môžeme nájsť v iných premenných referenčného typu, či referenciu na objekt nám môžu vrátiť metódy. Referenciu na objekt ale vracia aj príkaz new, ktorý už dlho používame. V skutočnosti príkaz new spraví to, že najprv vo "svete objektov" vytvorí a inicializuje objekt danej triedy, pričom výsledkom tejto operácie je referencia na vytvorený objekt (a túto hodnotu môžeme niekam uložiť, čo zvyčajne aj robíme).

WinPane plocha = new WinPane();

Guľaté zátvorky sú podobné zátvorkám pri volaní metód. V skutočnosti sa pri vytvorení a inicializácii objektu vykonáva tzv. konštruktor objektu, čo je špeciálna "metóda" (postupnosť príkazov), ktorá skonštruuje objekt. Konštruktory, tak ako všetky metódy, môžu mať aj parametre. Napríklad v prípade triedy WinPane, okrem konštruktora bez parametrov, existuje aj konštruktor s parametrami, ktorý vytvorí kresliacu plochu požadovaných rozmerov:

WinPane plocha = new WinPane(400, 200);

O tom, aké konštruktory majú tie-ktoré triedy, sa dozvieme v inej prednáške.

Pravidlá pre referencie a objekty

Pri práci s objektami a premennými referenčného typu by sme si mali zapamätať niekoľko pravidiel:

  • Nie je pravdou, že neinicializovaná premenná obsahuje hodnotu null. Hodnotu do neinicializovanej premennej treba vždy najprv priradiť.
  • Objekty sa vytvárajú príkazom new v spolupráci s konštruktorom (a ten môže mať parametre). Výsledkom príkazu je referencia na vytvorený objekt.
  • Objekty vieme len vytvoriť, nevieme ich "zničiť"
  • Jeden objekt môže referencovať mnoho premenných referenčného typu.
  • Ak objekt nie je referencovaný žiadnou premennou referenčného typu, t.j. nikde nie je uchovaná referencia naň, objekt je "stratený", lebo s ním nevieme komunikovať.

<< Debugovanie programov | Obsah | Typ char a znakové reťazce >>