Základní pojmy OOP. Třída, objekt, jeho vlastnosti. Metody, proměnné. Konstruktory.

Obsah

Třída, objekt, jejich vlastnosti
Co je třída a objekt?
Vlastnosti objektu (1)
Vlastnosti objektu (2)
Deklarace a použití třídy
Příklad - deklarace třídy Clovek
Příklad - použití třídy Clovek (1)
Příklad - použití třídy Clovek (2)
Vytváření objektů
Shrnutí
Proměnné
Proměnné - deklarace
Proměnné - datový typ
Proměnné - jmenné konvence
Proměnné - použití
Proměnné - modifikátory přístupu
Proměnné - použití (2)
Metody
Metody
Metody - příklad
Volání metod
Volání metod - příklad
Parametry metod
Předávání skutečných parametrů metodám
Příklad předávání parametrů - primitivní typy
Příklad předávání parametrů - objektové typy (1)
Příklad předávání parametrů - objektové typy (2)
Návrat z metody
Konstruktory
Konstruktory
Konstruktory (2)
Přetěžování metod
Přetěžování
Přetěžování - příklad
Přetěžování - příklad (2)
Přetěžování - příklad (3)
Odkazy na objekty (instance)
Odkazy na objekty (instance)
Přiřazování objektových proměnných
Vracení odkazu na sebe
Řetězení volání
Statické proměnné a metody
Proměnné a metody třídy - statické
Příklad statické proměnné a metody

Úvod do objektového programování

  • Pojmy: třída, objekt

  • Deklarace a definice tříd, jejich vlastnosti (proměnné, metody)

  • Vytváření objektů (deklarace sama objekt nevytvoří...), proměnné odkazující na objekt

  • Jmenné konvence - jak tvořit jména tříd, proměnných, metod

  • Použití objektů, volání metod, přístupy k proměnným

  • Modifikátory přístupu/viditelnosti (public, protected...)

  • 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

Co je třída a objekt?

Třída (také poněkud nepřesně zvaná objektový typ) představuje skupinu objektů, které nesou stejné vlastnosti

"stejné" je myšleno kvalitativně, nikoli kvantitativně, tj.

  • např. všechny objekty třídy Cloveksearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia mají vlastnost jmenosearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia,

  • tato vlastnost má však obecně pro různé lidi různé hodnoty - lidi mají různá jména

Objekt je jeden konkrétní jedinec (reprezentant, entita) příslušné třídy

pro konkrétní objekt nabývají vlastnosti deklarované třídou konkrétních hodnot

Příklad:

Vlastnosti objektu (1)

Vlastnostmi objektů jsou:

  • proměnné

  • metody

Vlastnosti objektů - proměnné i metody - je třeba deklarovat.

viz Sun Java Tutorial / Trail: Learning the Java Language: Lesson: Classes and Inheritance

Vlastnosti objektu (2)

Proměnné

  1. jsou nositeli "pasivních" vlastností; jakýchsi atributů, charakteristik objektů

  2. de facto jde o datové hodnoty svázané (zapouzdřené) v objektu

Metody

  1. jsou nositeli "výkonných" vlastností; "dovedností" objektů

  2. de facto jde o funkce (procedury) pracující (převážně) nad proměnnými objektu

Deklarace a použití třídy

Příklad - deklarace třídy Clovek

  • deklarujme třídu objektů - lidí

    public class Clovek { 
    
       protected String jmeno; 
       protected int rokNarozeni; 
    
       public Clovek(String j, int rN) { 
          jmeno = j; 
          rokNarozeni = rN;
       }
    
       public void vypisInfo() { 
          System.out.println("Clovek:");
          System.out.println("Jmeno="+jmeno); 
          System.out.println("Rok narozeni="+rokNarozeni); 
       }
    } 
    
  • Použijme ji v programu -

    1. vytvořme instanci - objekt - typu Cloveksearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia

    2. vypišme informace o něm

Příklad - použití třídy Clovek (1)

Mějme deklarovánu třídu Clovek

Metoda main v následujícím programu:

  1. vytvoří 2 lidi (pomocí new Clovek)

  2. zavolá jejich metody

    vypisInfo()search in Free On-line Dictionary of Computingsearch in Czech Wikipedia

    public class TestLidi { 
       public static void main(String[] args) { 
          Clovek ales = new Clovek("Ales Necas", 1966); 
          Clovek beata = new Clovek("Beata Novakova", 1970); 
          ales.vypisInfo();
          beata.vypisInfo(); 
       }
    } 
    

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 Clovek (2)

Ve výše uvedeném programu znamenalo na řádku:

Clovek ales = new Clovek("Ales Necas", 1966); 

Clovek alessearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia: pouze deklarace (tj. určení typu) proměnné ales - bude typu Clovek.

ales = new Clovek ("Ales Necas", 1966)search in Free On-line Dictionary of Computingsearch in Czech Wikipedia: vytvoření objektu Clovek se jménem Ales Necas.

Lze napsat zvlášť do dvou řádků nebo (tak jak jsme to udělali) na řádek jeden.

Každý příkaz i deklaraci ukončujeme středníkem.

Vytváření objektů

Ve výše uvedených příkladech jsme objekty vytvářeli voláními new Clovek(...)search in Free On-line Dictionary of Computingsearch in Czech Wikipedia bezděčně jsme tak použili

  • operátor new, který vytvoří prázdný objekt typu Clovek a

  • volání konstruktoru, který prázdný objekt naplní počátečními údaji (daty).

Shrnutí

Objekty:

  • jsou instance "své" třídy

  • vytváříme je operátorem newsearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia - voláním 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)

Proměnné

Proměnné - deklarace

Položky jmenosearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia a rokNarozenisearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia v předchozím příkladu jsou proměnné objektu Cloveksearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia.

Jsou deklarovány v těle deklarace třídy Clovek.

Deklarace proměnné objektu má tvar:

modifikátory Typ jméno;search in Free On-line Dictionary of Computingsearch in Czech Wikipedia

např.:

protected int rokNarozeni;search in Free On-line Dictionary of Computingsearch in Czech Wikipedia

Proměnné - datový typ

Výše uvedená proměnná rokNarozenisearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia měla datový typ int (32bitové celé číslo). Tedy:

  • proměnná takového typu nese jednu hodnotu typu celé číslo (v rozsahu -2^31.. 2^31-1);

  • nese-li jednu hodnotu, pak se jedná o tzv. primitivní datový typ.

Kromě celých čísel int nabízí Java celou řadu dalších primitivních datových typů. Primitivní typy jsou dané napevno, programátor je jen používá, nedefinuje.

Tam, kde nestačí diskrétní hodnoty (tj. primitivní typy), musíme použít typy složené, objektové.

  • Objektovými typy v Javě jsou třídy (class) a rozhraní (interface). Třídy už jsme viděli v příkladu Clovek.

  • Existují třídy definované přímo v Javě, v knihovně Java Core API.

  • Nenajdeme-li tam třídu, kterou potřebujeme, můžeme si ji nadefinovat sami - viz Clovek.

Proměnné - jmenné konvence

Na jméno (identifikátor) proměnné sice Java neklade žádná speciální omezení (tedy mimo omezení platná pro jakýkoli identifikátor), ale přesto bývá velmi dobrým zvykem dodržovat při pojmenovávání následující pravidla (blíže viz podrobný rozbor na FIXME):

  • jména začínají malým písmenem

  • nepoužíváme diakritiku (problémy s editory, přenositelností a kódováním znaků)

  • (raději ani český jazyk, angličtině rozumí "každý")

  • je-li to složenina více slov, pak je nespojujeme podtržítkem, ale další začne velkým písmenem (tzv. "CamelCase")

např.:

protected int rokNarozeni;search in Free On-line Dictionary of Computingsearch in Czech Wikipedia

je identifikátor se správně (vhodně) utvořeným jménem, zatímco:

protected int RokNarozeni;search in Free On-line Dictionary of Computingsearch in Czech Wikipedia

není vhodný identifikátor proměnné (začíná velkým písmenem)

Dodržování těchto 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.

Proměnné - použití

Proměnné objektu odkazujeme pomocí "tečkové notace":

public class TestLidi2 { 
   public static void main(String[] args) { 
      ... 
      Clovek ales = new Clovek("Ales Necas", 1966); // vytvoření objektu ...
      System.out.println(ales.jmeno); // přístup k (čtení) jeho proměnné ...
      ales.jmeno = "Aleš Novák"; // modifikace (zápis do) jeho proměnné 
   }
}    

Proměnné - modifikátory přístupu

Přístup k proměnným (i metodám) může být řízen uvedením tzv. modifikátorů před deklaraci prvku, viz výše:

// protected = přístup pouze z třídy ve stejném balíku nebo z podtřídy: 
protected String jmeno;

Modifikátorů je více typů, nejběžnéjší jsou právě zmíněné modifikátory přístupu (přístupových práv)

Proměnné - použití (2)

Objektů (tzv. instancí) stejného typu (tj. stejné třídy) si můžeme postupně vytvořit více:

public class TestLidi3 {
    public static void main(String[] args) { 
       ... 
       Clovek ales = new Clovek("Ales Necas", 1966); // vytvoření prvniho objektu 
       Clovek petr = new Clovek("Petr Svoboda", 1968); // vytvoření druheho objektu ...
       System.out.println(ales.jmeno); // přístup k (čtení) proměnné - prvnímu objektu
       System.out.println(petr.jmeno); // přístup k (čtení) proměnné - druhému objektu
    }
}   

Existují tady dva objekty, každý má své (obecně různé) hodnoty proměnných - např. jsou různá jména obou lidí.

Metody

Metody

Nad existujícími (vytvořenými) objekty můžeme volat jejich metody. Metoda je:

  • podporgram (funkce, procedura), který primárně pracuje s proměnnými "mateřského" objektu,

  • může mít další parametry

  • může vracet hodnotu podobně jako v Pascalu funkce.

Každá metoda se musí ve své třídě deklarovat.

V Javě neexistují metody deklarované mimo třídy (tj. Java nezná žádné "globální" metody).

Metody - příklad

Výše uvedená třída Clovek měla metodu na výpis informací o daném objektu/člověku:

public class Clovek { 
   protected String jmeno; 
   protected int rokNarozeni; 

   public Clovek(String j, int rN) { 
      jmeno = j; 
      rokNarozeni = rN; 
   } 
   // Metoda vypisInfo() na výpis informací o člověku: 
   public void vypisInfo() {
      System.out.println("Clovek:"); 
      System.out.println("Jmeno="+jmeno);
      System.out.println("Rok narozeni="+rokNarozeni); 
   }
}   

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í přístupná - "viditelná". Přístupnost regulují pdobně jako u proměnných modifikátory přístupu.

Volání metod - příklad

Vracíme se k prvnímu příkladu: vytvoříme dva lidi a zavoláme postupně jejich metodu

vypisInfo

.

public class TestLidi { 
   public static void main(String[] args) { 
      Clovek ales = new Clovek("Ales Necas", 1966); 
      Clovek beata = new Clovek("Beata Novakova", 1970); 
      ales.vypisInfo(); // volání metody objektu ales 
      beata.vypisInfo(); // volání metody objektu beata 
   }
}   

Vytvoří se dva objekty Clovek a vypíší se informace o nich.

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: search in Free On-line Dictionary of Computingsearch in Czech Wikipedia typParametru nazevFormalnihoParametru, ...search in Free On-line Dictionary of Computingsearch in Czech Wikipedia

Podobně jako v jiných jazycích parametr představuje v rámci metody lokální proměnnou.

Při volání metody jsou f. p. nahrazeny skutečnými parametry.

Předávání skutečných parametrů metodám

Hodnoty primitivních typů - čí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

    Pozn: 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

Clovek

o metodu

zakric

s parametry:

... 
public void zakric(int kolikrat) {
   System.out.println("Kricim " + kolikrat + "krat UAAAA!"); 
}
...   

Při zavolání:

... 
zakric(10); 
... 

tato metoda vypíše

Kricim 10krat UAAAA!

Příklad předávání parametrů - objektové typy (1)

Následující třída Ucet 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

public class Ucet { 
    // stav (zustatek) penez uctu 
    protected double zustatek; 

    public void pridej(double castka) { 
        zustatek += castka; 
    }

    public void vypisZustatek() {
        System.out.println(zustatek);
    }

    public void prevedNa(Ucet kam, double castka) { 
        zustatek -= castka; 
        kam.pridej(castka); 
    }
} 

Metoda prevedNa pracovat nejen se svým "mateřským" objektem, ale i s objektem kam předaným do metody... opět přes tečkovou notaci.

Příklad předávání parametrů - objektové typy (2)

Příklad použití třídy

Ucet

:

...
public static void main(String[] args) { 
   Ucet petruvUcet = new Ucet();
   Ucet ivanuvUcet = new Ucet(); 
   petruvUcet.pridej(100);
   ivanuvUcet.pridej(220); 
   petruvUcet.prevedNa(ivanuvUcet, 50);
   petruvUcet.vypisZustatek(); 
   ivanuvUcet.vypisZustatek(); 
}   

Návrat z metody

Kód metody skončí, tj. předá řízení zpět volající metodě (nebo systému - v případě startovní metody mainsearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia), jakmile

  • dokončí poslední příkaz v těle metody nebo

  • dospěje k příkazu returnsearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia

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 returnsearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia. 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 voidsearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia.

Pozn.: I když metoda něco vrátí, my to nemusíme použít, ale je to trochu divné...

Konstruktory

Konstruktory

Co a k čemu jsou konstruktory?

  • Konstruktury jsou speciální metody volané při vytváření nových instancí dané třídy.

  • Typicky se v konstruktoru naplní (inicializují) proměnné objektu.

  • Konstruktory lze volat jen ve spojení s operátorem newsearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia k vytvoření nové instance třídy - nového objektu, evt. volat z jiného konstruktoru

Syntaxe (viz výše):

public class Clovek { 
   protected String jmeno;
   protected int rokNarozeni; 
   // konstruktor se dvěma parametry 
   // - inicializuje hodnoty proměnných ve vytvořeném objektu 
   public Clovek(String j, int rN) { 
      jmeno = j;
      rokNarozeni = rn;
   }
   ...
} 

Příklad využití tohoto konstruktoru:

...
Clovek pepa = new Clovek("Pepa z Hongkongu", 1899); 
... 

Toto volání vytvoří objekt pepa a naplní ho jménem a rokem narození.

Konstruktory (2)

Jak je psát a co s nimi lze dělat?

  • nemají návratový typ (ani voidsearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia - to už vůbec ne!!!)

  • mohou mít parametry

  • mohou volat konstruktor rodičovské třídy - ale jen jako svůj první příkaz

Přetěžování metod

Přetěžování

Jedna třída může mít:

  • Více metod se stejnými názvy, ale různými parametry.

  • Pak hovoříme o tzv. přetížené (overloaded) metodě.

  • Nelze přetížit metodu pouze změnou typu návratové hodnoty.

Přetěžování - příklad

Ve třídě Ucetsearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia přetížíme metodu prevedNasearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia.

  • Přetížená metoda převede na účet příjemce celý zůstatek z účtu odesílatele:

public void prevedNa(Ucet u) { 
   u.pridej(zustatek); 
   zustatek = 0;
} 

Ve třídě

Ucet

koexistují dvě různé metody se stejným názvem, ale jinými parametry.

Pozn: I když jsou to teoreticky dvě úplně různé metody, pak když už se jmenují stejně, měly by dělat něco podobného.

Přetěžování - příklad (2)

  • Často přetížená metoda volá jinou "verzi" metody se stejným názvem:

    public void prevedNa(Ucet u) { 
       prevedNa(u, zustatek); 
    } 
    
  • Toto je jednodušší, přehlednější, udělá se tam potenciálně méně chyb.

    Lze doporučit. Je to přesně postup divide-et-impera, rozděl a panuj, dělba práce mezi metodami!

Přetěžování - příklad (3)

  • Je ale otázka, zdali převod celého zůstatku raději nenapsat jako nepřetíženou, samostatnou metodu, např.:

    public void prevedVseNa(Ucet u) { 
       prevedNa(u, zustatek); 
    }
    
  • Je to o něco instruktivnější, ale přibude další identifikátor - název metody - k zapamatování.

    Což může být výhoda (je to výstižné) i nevýhoda (musíme si pamatovat další).

Odkazy na objekty (instance)

Odkazy na objekty (instance)

Deklarace proměnné objektového typu ještě žádný objekt nevytváří.

To se děje až příkazem - operátorem - newsearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia.

  • Proměnné objektového typu jsou vlastně odkazy na dynamicky vytvořené objekty.

  • Přiřazením takové proměnné zkopírujeme pouze odkaz, nikoli celý objekt.

Přiřazování objektových proměnných

V následující ukázce vytvoříme dva účty.

  • Odkazy na ně budou primárně v proměnných petruvUcet a ivanuvUcet.

  • V proměnné u nebude primárně odkaz na žádný účet.

  • Pak do ní přiřadíme (u = petruvUcet;search in Free On-line Dictionary of Computingsearch in Czech Wikipedia) odkaz na objekt skrývající se pod odkazem petruvUcet.

  • Od této chvíle můžeme s účtem petruvUcet manipulovat přes odkaz (proměnnou) u.

    Což se také děje: u.prevedNa(ivanuvUcet, 50);search in Free On-line Dictionary of Computingsearch in Czech Wikipedia

 ... 
   public static void main(String[] args) { 
      Ucet petruvUcet = new Ucet(); 
      Ucet ivanuvUcet = new Ucet(); 
      Ucet u; 
      petruvUcet.pridej(100);
      ivanuvUcet.pridej(220);
      u = petruvUcet; 
      u.prevedNa(ivanuvUcet, 50); //  odečte se z Petrova účtu 
      petruvUcet.vypisZustatek(); // vypíše 50
      ivanuvUcet.vypisZustatek(); 
   } 

Vracení odkazu na sebe

Metoda může vracet odkaz na objekt, nad nímž je volána pomocí

return this; search in Free On-line Dictionary of Computingsearch in Czech Wikipedia

Příklad - upravený Ucetsearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia s metodou prevedNasearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia vracející odkaz na sebe

public class Ucet { 
   float zustatek; 

   public void pridej(float castka) { 
      zustatek += castka; 
   }

   public void vypisZustatek() { 
      System.out.println(zustatek); 
   } 

   public Ucet prevedNa(Ucet u, float castka) { 
      zustatek -= castka; // nebo také vhodné je: pridej(-castka); 
      u.pridej(castka); 
      return this;
   }
}   

Řetězení volání

Vracení odkazu na sebe (tj. na objekt, na němž se metoda volala) lze s výhodou využít k "řetězení" volání:

 ... 
   public static void main(String[] args) { 
      Ucet petruvUcet = new Ucet(); 
      Ucet ivanuvUcet = new Ucet(); 
      Ucet igoruvUcet = new Ucet(); 
      petruvUcet.pridej(100);
      ivanuvUcet.pridej(100); 
      igoruvUcet.pridej(100); 
// budeme řetězit volání:
      petruvUcet.prevedNa(ivanuvUcet, 50).prevedNa(igoruvUcet, 20);
      petruvUcet.vypisZustatek(); // vypíše 30 
      ivanuvUcet.vypisZustatek(); // vypíše 150 
      igoruvUcet.vypisZustatek(); // vypíše 120 
   }
    

Statické proměnné a metody

Proměnné a metody třídy - statické

Dosud jsme zmiňovali proměnné a metody (tj. souhrnně prvky - members) objektu.

Lze deklarovat také metody a proměnné patřící celé třídě, tj. skupině všech objektů daného typu. Takové metody a proměnné nazýváme statické a označujeme v deklaraci modifikátorem staticsearch in Free On-line Dictionary of Computingsearch in Czech Wikipedia

Příklad statické proměnné a metody

Představme si, že si budeme pamatovat, kolik lidí se nám během chodu programu vytvořilo a vypisovat tento počet.

Budeme tedy potřebovat do třídy Clovek doplnit:

  • jednu proměnnou pocetLidi společnou pro celou třídu Clovek - každý člověk ji při svém vzniku zvýší o jedna.

  • jednu metodu kolikMamLidi, která vrátí počet dosud vytvořených lidí.

public class Clovek { 

   protected String jmeno; 
   protected int rokNarozeni; 
   protected static int pocetLidi = 0; 

   public Clovek(String j, int rN) { 
      jmeno = j; 
      rokNarozeni = rn;
      pocetLidi++;
   } 
   ... 
   public static int kolikMamLidi() { 
      return pocetLidi; 
   }
   ... 
} 

Pozn: Všimněte si v obou případech modifikátoru/klíčového slova static.