37
Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy a objekty Deklarace třídy a objektu, vytvoření objektu Proměnné primitivní vs. objektové Přímý přístup k atributům a metodám Program sestávající z více tříd Konstruktor a klíčové slovo this Autorizovaný přístup Vytváření, volání a přetěžování metod Pole objektů třídy String - příklad knihovní třídy Metody třídy String a jejich použití Třída StringBuffer* Programování procedurální vs. objektové Tato tematika je zpracována v Záznamy přednášek: str. 123 152 Prostudujte i motivační příklad Osoba - BMI! Budete ho potřebovat na cvičení a při řešení domácích úloh.

Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška

Obsah 6. přednášky:

Třídy a objekty

Deklarace třídy a objektu, vytvoření objektu

Proměnné primitivní vs. objektové

Přímý přístup k atributům a metodám

Program sestávající z více tříd

Konstruktor a klíčové slovo this

Autorizovaný přístup

Vytváření, volání a přetěžování metod

Pole objektů třídy

String - příklad knihovní třídy

Metody třídy String a jejich použití

Třída StringBuffer*

Programování procedurální vs. objektové

Tato tematika je zpracována v

Záznamy přednášek: str. 123 – 152

Prostudujte i motivační příklad Osoba - BMI! Budete ho potřebovat na cvičení a při řešení domácích úloh.

Page 2: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 2 (celkem 37)

Třídy a objekty

Programování - procedurální (dosud) - objektové (OOP – objektově orientované

programování)

Motivace vzniku OOP

Dekompozice problému s velkým množstvím detailů na dílčí zvládnutelné problémy, s možností řešení současně více programátory

Simula 67 (1967, Norwegian Computing Center)

– základem byl Algol 60 (bloková struktura)

Blok (podprogram), nezávislý na zbytku programu

- formální popis – vzor seskupení dat, algoritmů a akcí

- vykonání - vytvoření dynamické instance

Java – třída jako nový datový typ

Třída (class)

- základní jazyková konstrukce OOP

- šablona (template) objektový typ, pro dynamické vytváření objektů této třídy

- členské /instanční proměnné /atributy (stav)

- členské /instanční metody (chování)

Page 3: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 3 (celkem 37)

Příklad: třída Kruh

Kruh o poloměru r s výpočtem plochy P

Příklad objektů třídy Kruh

P = 3.14

r = 1

1

P = r2

r

Kruh

double polomer

double spoctiPlochu()

mujKruhZluty

polomer = 1.0 P = 3.14

mujKruhModry

polomer = 2.0 P = 12.56

P = 12.56

r = 2

Objekt (object), instance (instance)

- datový prvek (množina hodnot a množina operací), vytvořený dle vzoru třídy

Page 4: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 4 (celkem 37)

Deklarace třídy a objektu, vytvoření objektu

Deklarace třídy

Příklad:

class Jmeno { typ a jmeno atributu, inicializace typ a jmeno metody() { ...

telo metody ...

} }

Deklarace a vytvoření objektu

Přístup k objektům

- prostřednictvím referenční proměnné

např. mujKruhZluty, mujKruhModry

class Kruh {

double polomer = 1.0;

double spoctiPlochu() { return 3.14*polomer*polomer; } }

Page 5: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 5 (celkem 37)

Deklarace objektu

JmenoTridy jmenoObjektu;

Příklad:

Vytvoření objektu

jmenoObjektu = new JmenoTridy();

Příklad:

Kruh mujKruh;

mujKruh = new Kruh();

null

mujKruh

referenční proměnná

mujKruh

polomer = 1

Kruh

objekt referenční

proměnná

Page 6: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 6 (celkem 37)

Deklarace a vytvoření objektu současně

JmenoTridy jmenoObjektu = new JmenoTridy();

Příklad:

Zrušení objektu (Garbage collector) - pokud na objekt není reference Příklad:

Kruh mujKruh = new Kruh();

mujKruh = null;

mujKruh

null

referenční

proměnná

polomer = 1

Kruh

objekt

Page 7: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 7 (celkem 37)

Proměnné primitivní vs. objektové

Rozdíl v pojetí

- při deklaraci a vzniku

- při přiřazení proměnných

int i = 1; Kruh k1 = new Kruh(5); int j = 2; Kruh k2 = new Kruh(9);

???

Kruh

polomer = 1

Primitivní typ int i; i

i = 1; i

Objektový typ Kruh k = new Kruh();

null

k

k při deklaraci

při vytvoření

1

při deklaraci

při vytvoření

1

Kruh

polomer = 5

Přiřazení: primitivní typ i = j

před:

i

2 j

2

po:

i

2 j

Přiřazení: typ objekt k1 = k2

před:

k1

k2

po:

k1

k2

polomer = 9

Kruh

Page 8: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 8 (celkem 37)

Přímý přístup k objektu tj. k atributům a metodám

Reference atributu či metody - tečkovaná notace

Komunikace s objektem - zasíláním zpráv (volání instančních metod)

Reference atributu

jmenoObjektu.promenna

Př.:

Reference metody

jmenoObjektu.metoda()

Př.:

Program sestávající z více tříd

Deklaraci, vytvoření a použití objektu (tj. atributů a metod) provádíme v jiné třídě. Na počátku, pro jednoduchost, budeme vytvářet a používat programy sestávající pouze ze dvou tříd.

Hlavní program - tj. třída obsahující main()

- zde budeme programy spouštět.

Pokud program sestává z více tříd, každou třídu ukládáme do samostatného souboru (výjimkou je

odevzdání DÚ na validátor). Důvodem je snadné použití třídy v jiném programu či předání třídy (souboru) jinému programátorovi.

mujKruh.spoctiPlochu()

mujKruh.polomer

Page 9: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 9 (celkem 37)

Poznámky:

Uložení programu - pokud jsou třídy výjimečně uloženy společně v jednom souboru, potom je pouze třída s hlavním programem, tj. s metodou main(), opatřena modifikátorem public!

Překlad programu

třída:

- příkazová řádka: javac JmenoTridy.java

- Scite: Ctrl+F7

celý program:

- příkazová řádka: javac *.java

- Scite: F7

Spouštění programu

třída:

- příkazová řádka: java JmenoTridy

- Scite: F5

celý program:

- příkazová řádka: java HlavniProgram

- Scite: F5 v hlavní třídě

Terminologie - poznámka

- pro označení třídy jakožto šablony se lze setkat s pojmem „datová třída“ (Data Model Class), tj. třída sloužící zejména k uchování dat a manipulaci s nimi. Instancí takové třídy je datový objekt (Data Object).

Page 10: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 10 (celkem 37)

Příklad vytvoření a použití objektu

Výpis výsledků v předchozím příkladu je zbytečně zdlouhavý, a kdykoliv budeme potřebovat vypsat poloměr či plochu musíme příkazy zopakovat.

class Kruh {

double polomer = 1.0;

double spoctiPlochu(){ return 3.14*polomer*polomer; } }

TŘÍDA KRUH

public class TestKruhu { public static void main(String[] args){ // main()-entry point

Kruh mujKruh = new Kruh(); // vytvoreni //polomer nastaven na inicializovanou hodnotu atributu tridy

System.out.println("Polomer = " + mujKruh.polomer);

mujKruh.polomer = 10;// nastaveni nove hodnoty polomeru

// vypis

System.out.println("Plocha kruhu o polomeru " + mujKruh.polomer + " je " + mujKruh.spoctiPlochu() + ".");

} }

Polomer = 1.0 Plocha kruhu o polomeru 10.0 je 314.1592653589793.

HLAVNÍ PROGRAM TŘÍDA - obsahující main() (ŘÍDICÍ, APLIKAČNÍ, UŽIVATELSKÁ)

Page 11: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 11 (celkem 37)

Řešením je použití metody String toString(),

(vrací řetězec se stavem objektu), napíšeme ji dle potřeby ve třídě Kruh a pak tuto metodu zavoláme (v metodě pro výpis) v hlavním programu (viz dále).

public class TestKruhu {

public static void main(String[] args){

Kruh mujKruh = new Kruh();

System.out.println("Polomer = " + mujKruh.polomer);

mujKruh.polomer = 10;

// vhodnejsi zpusob vypisu

System.out.println(mujKruh.toString()); // staci pouze zapis bez uvedeni toString()

System.out.println(mujKruh); } }

class Kruh {

double polomer = 1.0;

double spoctiPlochu(){ return 3.14*polomer*polomer; }

/** Vypis objektu pouzitim metody toString() (pretizena metoda) * @return String retezec s informaci o objektu */

public String toString(){ return "<Kruh: polomer = " + polomer + ", plocha = " + spoctiPlochu() + ">"; } }

Page 12: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 12 (celkem 37)

Konstruktor a klíčové slovo this

Konstruktor - speciální metoda, která umožňuje vytvoření objektu (přidělení paměti a inicializace členských proměnných)

Liší se od ostatních metod: - nelze volit jeho jméno, má jméno třídy

- nemá žádnou návratovou hodnotu (tj. ani void)

- nelze volat rekurzivně

- použití operátoru new

Konstruktor

- implicitní – vytvoří se, i když ho nenapíšeme

(předchozí příklad fungoval! Volali jsme Kruh(), ale ve třídě Kruh konstruktor zapsán nebyl)

- explicitní – nutno napsat (může být i přetížen, tj. konstruktorů můžeme napsat více)

Použití klíčového slova this

- typicky se vyskytuje v konstruktoru, ale i jinde (viz dále)

Formální parametry konstruktoru mají často jméno shodné s atributem – nutno odlišit.

Řešením je

this.jmenoAtributu

neboť this odkazuje vždy na samotný objekt.

Upravíme tedy náš předchozí příklad:

Page 13: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 13 (celkem 37)

public class Kruh { double polomer;

Kruh(double polomer) { // konstruktor

this.polomer = polomer; // this zde musí byt

}

Kruh(){ /* konstruktor bez parametru, musi byt napsan, ale jen pokud jej potrebujeme, tzv. pretizeny konstruktor */

polomer = 1.0; // this zde neni nutné, nelze pochybit

} double spoctiPlochu(){ return polomer*polomer*Math.PI; } // this by mohlo byt uvedeno, ale zatim nadbytecne

.... } public class TestKruhuSKonstruktory { //aplikace

public static void main(String[] args) {

// nastav polomer 5.0

Kruh mujKruh = new Kruh(5.0);

// vypocet a tisk

System.out.println(mujKruh);

// defaultni polomer

Kruh tvujKruh = new Kruh();

// vypocet a tisk

System.out.println(tvujKruh); } }

<Kruh: polomer = 5.0, plocha = 78.53981633974483>

<Kruh: polomer = 1.0, plocha = 3.141592653589793>

Page 14: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 14 (celkem 37)

Autorizovaný přístup

Uživatel se pohodlně dostává přímým přístupem k nastavení atributu - výhoda, ale tím pádem může

tento atribut i nevhodně změnit - nevýhoda (např. v našem případě zadat záporný poloměr!)

Řešení - použít modifikátor (specifikátor) private

(privátní, soukromý)

- zapouzdření (encapsulation) – skrytí atributů před „vnějšími vlivy“

Přístupová práva:

Důsledek - použitím specifikátoru private přímý

přístup k atributu již nefunguje!

Nutný autorizovaný přístup, tj. - vytvoření přístupových metod pro nastavení a vrácení hodnoty atributu (setters, getters)

Poznámka:

Přístupové právo metod bývá většinou public, ale i metody je

možné (někdy vhodné) skrývat, potom je použit modifikátor private (s důsledky obdobnými jako u atributu).

Specifikátor Povolený přístup

public Z libovolné třídy.

private Pouze zevnitř dané třídy, žádný přístup z vnějšku.

protected Z kterékoliv třídy téhož balíku, případně z potomka třídy kdekoliv.

žádný (tzv. package friendly)

Z kterékoliv třídy téhož balíku.

Page 15: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 15 (celkem 37)

Úprava: přidáme modifikátor private pro atribut

polomer a přístupové metody getPolomer() a setPolomer()

public class Kruh { private double polomer; // privatni atribut

public Kruh() { polomer = 1.0; }

public Kruh(double polomer) { setPolomer(polomer); // volani setru v konstruktoru }

// metoda pristupu k atributu vraceni hodnoty = getr

public double getPolomer() { return polomer; }

// metoda pristupu k atributu nastaveni hodnoty = setr public void setPolomer(double polomer) { if(polomer > 0){ //osetri pripustnost vstupu this.polomer = polomer; } }

double spoctiPlochu(){ return polomer*polomer*Math.PI; }

public String toString(){ return "<Kruh: polomer = " + polomer + ", plocha = " + spoctiPlochu() + ">"; } }

Page 16: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 16 (celkem 37)

Vytváření, volání, přetěžování metod

Vytváření

- píšeme dle běžných konvencí - instanční metody - static ne! (instance je

dynamická)

Volání

- z aplikační třídy (použít referenci na objekt, který metodu volá!)

- v rámci stejné třídy (běžné konvence)

Přetěžování

- platí stejná pravidla jako pro statické metody

public class TestKruhuSPrivateModifikatorem {

public static void main(String[] args) { // Vytvor kruh a nastav polomer 5.0 Kruh mujKruh = new Kruh(5.0);

/* Toto uz nelze pouzit!!! System.out.println(mujKruh.polomer); */

// vypocet a tisk System.out.println(mujKruh);

// Zvetsi polomer o 10%

mujKruh.setPolomer(mujKruh.getPolomer()*1.1); System.out.println(mujKruh); } }

<Kruh: polomer = 5.0, plocha = 78.53981633974483> <Kruh: polomer = 5.5, plocha = 95.03317777109125>

Page 17: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 17 (celkem 37)

Pole objektů třídy

- větší počet objektů: soubor položek stejného typu - vhodné použít pole (jako dříve)

Motivační příklad

1 2 3 4$

0

Rex

Lady Lord

null null

1 2 3 0

smeckadatum

objekt Pes

objekt Pes

objekt Pes

4

stene

pole referencí na objekty Pes Pes

Pes stene = new Pes ("Rex"); Pes [] smecka = { new Pes("Lord", stene, new Pes ("Lady") };

Vytvořeny 3 objekty:

Pes - objekt referencovaný jako stene a smecka[1]

Pes - objekt referencovaný jako smecka[0]

Pes - objekt referencovaný jako smecka[2]

Pes[] - pole objektů referencované jako smecka

Page 18: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 18 (celkem 37)

Úprava příkladu Kruh (aplikační třídy TestKruhu.java):

Úkol - vytvořme několik objektů typu Kruh a seřaďme je podle velikosti ploch

Řadíme reference nikoliv objekty!

Upravovat budeme pouze aplikační třídu, do které doplníme mimo jiné i metodu řazení.

Přidáme statickou metodu pro vytvoření pole objektů Kruh a statickou metodu řazení podle velikosti plochy, zvolíme metodu InsertSort ,

kterou upravíme pro řazení objektů.

Pozor: Porovnávání při řazení – nutno použít reference na atribut či metodu!

Všimněte si příkazu:

p = tmp.spoctiPlochu();

výpočet p odstraní několikanásobné použití

reference metody (a tudíž počítání hodnoty, která

se nemění) v cyklu while!

Výstup programu z následující stránky:

[<Kruh: polomer = 3.0, plocha = 28.274333882308138> , <Kruh: polomer = 2.0, plocha = 12.566370614359172> , <Kruh: polomer = 3.0, plocha = 28.274333882308138> ] [<Kruh: polomer = 2.0, plocha = 12.566370614359172> , <Kruh: polomer = 3.0, plocha = 28.274333882308138> , <Kruh: polomer = 3.0, plocha = 28.274333882308138> ]

Page 19: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 19 (celkem 37)

import java.util.*; public class TestKruhuPoleObjektu {

static private Random r = new Random();

public static Kruh[] vytvorKruhy(int pocetKruhu){ Kruh [] kruhy = new Kruh [pocetKruhu]; for(int i=0;i<kruhy.length;i++){ kruhy[i] = new Kruh(r.nextInt(pocetKruhu)+1); } return kruhy; }

public static void seradPodlePlochy(Kruh kruhy[]) { for (int i=0; i<kruhy.length; i++) { Kruh tmp = kruhy[i]; int j=i; double p = tmp.spoctiPlochu(); while((j>0) && (kruhy[j-1].spoctiPlochu() > p)) { kruhy[j]=kruhy[j-1]; j--; } kruhy[j]=tmp; } }

public static void main(String[] args) {

int pocetKruhu = r.nextInt(5)+1; Kruh [] kruhy = vytvorKruhy(pocetKruhu); System.out.println(Arrays.toString(kruhy)); seradPodlePlochy(kruhy); System.out.println(Arrays.toString(kruhy)); } }

Page 20: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 20 (celkem 37)

Příklad: náš první program Pozdrav - objektově

public class HelloWorld {

public static void main(String[] args) { Pozdrav pozdrav = new Pozdrav("Ahoj světe!"); pozdrav.print(); // 1. zpusob System.out.println(pozdrav); // 2. zpusob

// nyni se pozdrav zmeni, puvodni je uz nedostupny

pozdrav = new Pozdrav("Hello world!"); pozdrav.print(); System.out.println(pozdrav); } }

class Pozdrav { private String text;

public Pozdrav(String pozdrav) { // konstruktor

text = pozdrav; } // privatni metoda - privatni getr

private String getText() { // zde private ok

return text; } // 1 - metoda pro vypis

public void print() { // public metoda vola privatni getr System.out.println(getText()); } // 2 - metoda pro vypis

public String toString(){ // public metoda vola privatni getr return getText(); } }

Ahoj světe! Ahoj světe! Hello world! Hello world!

Poznámka pro odevzdávání DÚ na validátor: Validátor pracuje pouze s jedním souborem. Takže, kdybychom chtěli např. odevzdat předchozí příklad, pak třídu Pozdrav uvedeme bez specifikátoru

public a uložíme spolu do souboru s HelloWorld (v tomto souboru tedy

budou dvě třídy). Pouze aplikační třída může mít specifikátor public.

Takto upravený výsledný soubor odešleme na validátor.

Page 21: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 21 (celkem 37)

Poznámka (podrobně - viz Záznamy - str. 127): Na cvičení a

v DÚ bude používán lékařský termín BMI (Body Mass Index), který nemá nic společného s programováním. Je pouze použit pouze pro příklad výpočtu dat odvozených z dat základních.

BMI: podíl hmotnosti [kg] a čtverce výšky [m], tj.

BMI = m / (v * v)

Hodnoty BMI:

< 18 – podváha 18 až 25 – ideální hmotnost 25 až 30 – nadváha > 30 – obezita ohrožující zdraví

Příklad: vytvoříme třídu Osoba s atributy jmeno, vaha, vyska s konstruktorem Osoba() s metodami: getJmeno(), getVaha(), setVaha(),

getVyska() a vypoctiBMI() (viz slide na následující stránce)

Dále si vytvoříme v aplikační třídě objekt třídy Osoba, tj. osobu Hana, s vahou 50 kg a výškou 170 cm. Vypíšeme informace o objektu, jméno a spočtené BMI. Potom nastavíme váhu Hany na 55 kg a opět „objekt“ (tj. informace o něm) vypíšeme.

public class OsobyObjektyAplikace { public static void main(String[] args) { Osoba o; o = new Osoba("Hana", 50, 170); System.out.println(o.toString()); System.out.println(o.getJmeno() + " ma BMI " + o.vypoctiBMI()); o.setVaha(55.0); System.out.println(o); } }

<Hana, vaha: 50.0, vyska: 170, BMI: 17> Hana ma BMI 17

<Hana, vaha: 55.0, vyska: 170, BMI: 19>

Page 22: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 22 (celkem 37)

class Osoba { private String jmeno; // atributy private double vaha; private int vyska; // konstruktor public Osoba(String jmeno, double vaha, int vyska) { this.jmeno = jmeno; setVaha(vaha); this.vyska = vyska; } // getry a setry public String getJmeno() { return jmeno; } public double getVaha() { return vaha; } public void setVaha(double vaha) { if (vaha > 0.0) { this.vaha = vaha; } } public int getVyska() { return vyska; } // ostatni metody public int vypoctiBMI() { double vyskaMetry = vyska / 100.0; double bmi = vaha / (vyskaMetry * vyskaMetry); return (int) Math.round(bmi); // zaokrouhleni }

public String toString() { return "\n<" + jmeno + ", vaha: " + vaha + ", vyska: " + vyska + ", BMI: " + vypoctiBMI() + ">"; } }

Page 23: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 23 (celkem 37)

String - příklad knihovní třídy

- jedna z nejpoužívanějších tříd (cca 50 metod) - inicializovaný objekt typu String: deklarace

proměnné typu String a přiřazení řetězce v uvozovkách (i bez operátoru new)

- řetězcový literál (v uvozovkách) - automatické vytvoření objektu typu String

- řetězec je speciální „pole“ znaků, 0 až length()-1

- jednou vytvořený řetězec je konstantní, nelze jej měnit („měnitelný“ řetězec - třída StringBuffer)

- spojení řetězců (konkatenace) použitím operátoru + - řetězec jako operand následovaný operandem

jiného typu se automaticky převede na řetězec

Volání metod a práce s řetězci

String s = "ahoj", s1 = "hi", s2 = "bye";

s.jmenoMetody(), s1.jmenoMetody(s2)

Např.:

String s = "Ahoj"; char c = s.charAt(0); // A = znak na pozici 0

// s2 odkazuje na stejny objekt jako s1 // takto budeme prednostne pouzivat String s1 = "retezec"; String s2 = s1;

// skutecne vytvoreni noveho objektu, na nejz odkazuje s3 String s3 = new String(s1); System.out.println("s1: " + s1);

s1: retezec s2: retezec s3: retezec

Page 24: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 24 (celkem 37)

Práce se znaky

Porovnávání řetězců

Příklad: totožnost - výsledek true/false

Příklad: hodnotou - výsledek (0: rovnost, <0: první je menší, >0: druhé je menší)

Práce s podřetězci

Test začátku a konce řetězce

String s = "Ahoj";

int i = s.length(); // pocet znaku retezce vysledek i=4

int j = s.indexOf('a'); // první výskyt znaku 'a'

int k = s.lastIndexOf('o'); // index posledního výskytu 'o'

String s1 = "Ahoj";

String s2 = "ahoj"; boolean shoda = s1.equals(s2); // false

String s1 = "Ahoj";

String s2 = "ahoj";

int k = s1.compareTo(s2); // <0

String s = "proto"; int i = s.indexOf("to"); // výsledek i= 3

String p = s.substring(2); // výsledek p="oto"

String s = "proto"; boolean z = s.startsWith("pr"); // výsledek z = true

boolean k = s.endsWith(''ale"); // výsledek z = false

Page 25: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 25 (celkem 37)

Náhrada všech určených znaků

Oříznutí bílých znaků

Spojení řetězců (konkatenace)

Převod řetězce na pole znaků a zpět

KONVERZE:

A. Řetězec → základní datové typy

Datové typy int, double, long, ... mají své obalovací třídy: Integer, Double, Long, ...

String s = "\t ahoj \t\n\r";

s = s.trim(); // ahoj

String s2,s1 = "cacao";

s2 = s1.replace('c', 'k'); // vysledek kakao

String s1 = "Pan"; String s2 = "TAU"; // operatorem +

String s3 = s1 + " " + s2; // metodou concat()

String s4 = s1.concat(" " + s2); // Pan TAU

String s1 = "retezec"; char poleznaku[] = s1.toCharArray(); // pouziti pretizeneho konstruktoru

String s2 = new String(poleznaku);

Page 26: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 26 (celkem 37)

1. Metoda parse() volána ve tvaru:

ObalovaciTrida.parseTyp (s) … s je String Integer.parseInt(s), Long.parseLong(s), Double.parseDouble(s)

2. Metoda valueOf() volána ve tvaru:

ObalovaciTrida.valueOf (s) … s je String Integer.valueOf(s), Long.valueOf(s), Double.valueOf(s)

B. Základní datové typy → řetězec

1. Metoda toString() volána ve tvaru:

ObalovaciTrida.toString (x) … x je primitivní datový typ Integer.toString(), Long.toString(), Double.toString(), …

2. Metoda valueOf() volána ve tvaru:

String.valueOf(x) … x je primitivní datový typ String.tvalueOf(x),

// Prevod retezce na celociselny typ

// 1. zpusob

String s1 = "123"; int i = Integer.parseInt(s1); // i = 123

// 2. zpusob String s2 = "123.45";

double p = Double.valueOf(s2) ; // p = 123.45

Page 27: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 27 (celkem 37)

Další užitečné metody a třídy pro práci s řetězci

o metoda split(), třída StringTokenizer

Podrobné informace - JavaCoreAPI (String)

Příklad 1: Zpracování dat na vstupu (ilustrace

použití třídy String a metod: trim(),

split(), parseInt())

Na vstupu je neznámý počet dvojic čísel, každá dvojice

na jednom řádku, čísla navzájem oddělena mezerou,

úkolem je postupné načtení zpracování.

String input; String [] idata = new String[2]; // použije split()

int a, b; while (sc.hasNext()) { input = sc.nextLine().trim(); idata = input.split(" "); // oddelovac 1 mezera a = Integer.parseInt(idata[0]); b = Integer.parseInt(idata[1]); }

// Prevod celociselneho typu na retezec

// 1. zpusob int i = 123; String s3 = Integer.toString(i); // s3 = "123"

// 2. zpusob

double p = 123.45;

String s4 = String.valueOf(p) ; // s4 = "123.45"

Page 28: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 28 (celkem 37)

Příklad 2: Zjistěte, zda se zadané písmeno v řetězci

vyskytuje, a pokud ano, pak na které pozici je jeho první

výskyt, pokud ne, pouze vypište zprávu.

import java.util.Scanner; public class HledaniPismenaVRetezci { private static Scanner sc = new Scanner(System.in); public static void main(String[] args) { System.out.print("Zadejte retezec:"); String retezec = sc.nextLine(); System.out.print("Zadejte hledane pismeno:"); char hledej = sc.nextLine().charAt(0); boolean nalezeno = false; int index = 0;

// nasledujici programovou sekvenci bychom museli napsat

/* for(int i = 0; i < retezec.length(); i++) { // cyklem

if(retezec.charAt(i) == hledej){ nalezeno = true; index = i+1; break; } } */

if((index = retezec.indexOf(hledej))>=0) { // knihovni metodou

index++; nalezeno = true; } if(nalezeno) { System.out.println("Pismeno '"+ hledej + "' je na pozici:" + index); } else { System.out.println("Pismeno '"+ hledej + "' nenalezeno!"); } } }

Zadejte retezec:alenka Zadejte retezec:alenka Zadejte hledane pismeno:a Zadejte hledane pismeno:o Pismeno 'a' je na pozici:1 Pismeno 'o' nenalezeno!

Page 29: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 29 (celkem 37)

Př. 3: Césarova šifra - vytvořte program pro šifrování

textu (pouze malá písmena anglické abecedy), které

spočívá v posouvání znaku v abecedě o určitý, pevně

stanovený počet znaků. Např. slovo "ahoj" se posunem

textu o 1 znak transformuje na "bipk".

Další podobnou úložku hledejte na konci přednášky…

import java.util.*; public class CesarovaSifra { private static Scanner sc = new Scanner(System.in); public static void main(String [] args){ // inicializace promennych

String s = "abcdefghijklmnopqrstuvwxyz"; System.out.printf("Puvodni zprava: %s\n", s); String zprava = ""; int posun = 1; // posun mozno nastavit: sc.nextInt(); // cyklus prochazejici jednotlive znaky for (char c : s.toCharArray()) { // for Each

int i = (int)c; i += posun; // presun na zacatek abecedy if (i > (int)'z') { i -= 26; //pocet pismen } char znak = (char)i; zprava += znak; } // vypis System.out.printf("Zasifrovana zprava: %s\n", zprava); } }

Puvodni zprava: abcdefghijklmnopqrstuvwxyz Zasifrovana zprava: bcdefghijklmnopqrstuvwxyza

Page 30: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 30 (celkem 37)

Jednoduchý příklad: použití String a objektu

- pro připomenutí základů objektového programování

Třída DomaciZvirata obsahující: - dvě proměnné: druh zvířete a zvuk, který vydává - dva konstruktory - žádnou metodu

public class AplikaceDomaciZvirata { public static void main(String[] args) { // deklarace s inicializaci: instance pes DomaciZvirata alik = new DomaciZvirata(); alik.druh = "pes"; alik.zvuk = "haf"; // vytvorime novou instanci zvirete: kocku DomaciZvirata mica = new DomaciZvirata("kocka","mnau"); System.out.println("Jsem " + alik.druh + " a delam " + alik.zvuk); System.out.println("Jsem " + mica.druh + " a delam " + mica.zvuk); DomaciZvirata pipina = new DomaciZvirata("slepice","kokodak"); System.out.println("Ja jsem " + pipina.druh + " a delam " + pipina.zvuk); // ukazka NullPointerException, odkomentujte nasledujici radek

// pipina = null; // objekt nevytvoren System.out.println("" + pipina.zvuk.concat(", kokodak") + " :to je " + pipina.druh);

} }

class DomaciZvirata { // druh a zvuk, ktery zvire vydava public String druh; public String zvuk; public DomaciZvirata() { //konstruktor } public DomaciZvirata(String druh, String zvuk) { // konstruktor this.druh = druh; this.zvuk = zvuk; } }

Jsem pes a delam haf Jsem kocka a delam mnau Jsem slepice a delam kokodak kokodak, kokodak :to je slepice

Page 31: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 31 (celkem 37)

A lépe: třídu DomaciZvirata doplníme metodami kdoJe() a

jakDela() a metodou toString()

class DomaciZvirata { // doplneni metod public String druh; public String zvuk; public DomaciZvirata(){ } public DomaciZvirata(String druh, String zvuk){ this.druh = druh; this.zvuk = zvuk; } public String jakDela(){ return zvuk; } public String kdoJe(){ return druh; } public String toString(){ return "<zvire: " + kdoJe() + " ... " + jakDela() + ">"; } }

public class AplikaceKockaAPes { public static void main(String[] args) { DomaciZvirata alik = new DomaciZvirata(); alik.druh = "pes"; alik.zvuk = "haf"; DomaciZvirata mica = new DomaciZvirata("kocka","mnau");

// použiti doplnene metody

System.out.println("zvire: " + alik.kdoJe() + " ... " + alik.jakDela()); System.out.println("zvire: " + mica.kdoJe() + " ... " + mica.jakDela()); DomaciZvirata pipina = new DomaciZvirata("slepice","kokodak");

// zjednoduseni vypisu pouzitim metody toString() System.out.println(pipina); } }

Page 32: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 32 (celkem 37)

Třída StringBuffer* (pouze informace) - objekty typu String jsou řetězce neměnitelné - vyšší

odolnost vůči chybám a efektivnější zacházení

- měnitelné řetězce - použít instance třídy StringBuffer.

- doporučení - používat instance třídy String, je-li třeba změny - zkonvertovat na typ StringBuffer a pak opět uchovat v objektech typu String.

Převod objektu StringBuffer na String a zpět

Převod StringBuffer na String se provede metodou toString. Převod ze String na StringBuffer se provede vhodným použitím operátoru new (je to zcela intuitivní).

Ze String do StringBuffer: StringBuffer jmenobuf = new StringBuffer("Pepa "); Ze StringBuffer do String String jmeno = jmenobuf.toString();

Základy práce s třídou StringBuffer append(), insert ()- přidávání a vkládání textu

// vytvoreni objektu StringBuffer (s kapacitou 16 znaku)

StringBuffer jmenobuf2 = new StringBuffer(); String jmeno = "princezna Lada";

// vytvoreni objektu StringBuffer s pouzitim tridy String StringBuffer jmenobuf1 = new StringBuffer(jmeno);

// vytvoreni objektu StringBuffer s kapacitou zadanou cislem

StringBuffer jmenobuf2 = new StringBuffer(20);

StringBuffer buf = new StringBuffer("jmeno :"); buf.append(" Koza"); buf.insert(8, " Oliver") // vystup: "jmeno : Oliver Koza"; System.out.println(buf.toString());

Page 33: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 33 (celkem 37)

replace() - změna textu ve StringBufferu

capacity() - zjištění kapacity StringBufferu.

Kapacita představuje maximalní počet znaků, který lze do StringBufferu uložit.

reverse() - obrácení textu ve StringBufferu

Užitečné testování znaků

Character.isDigit()- je znak číslice?

Character.isLetter()- je znak písmeno?

Character.isLetterOrDigit()- je znak písmeno

nebo číslice?

Character.isLowerCase()- je znak malé písmeno?

Character.isUpperCase()- je znak velké písmeno?

Character.isWhitespace()- je to „bílý“ znak?

StringBuffer buf = new StringBuffer("Miroslav Koula"); String s1 = "Mirek"; // nahradi text zacinajici na pozici 1 až 8 novym textem buf.replace(1,8,s1);

StringBuffer buf = new StringBuffer("delsi retezec"); // delka je nastavena na 10 buf.setLength(10); // ale do kapacity je ulozena hodnota 14

int kapacita = buf.capacity();

StringBuffer obraceni = new StringBuffer("Radar"); System.out.println("Obraceni Radar: " + obraceni.reverse());

Page 34: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 34 (celkem 37)

Programování procedurální vs. objektové V následujícím příkladu je patrný rozdíl mezi procedurálním a objektovým programováním.

Obě formy mají své výhody a nevýhody!

Objektové programování představuje více „administrativy“, kód je však strukturovaný a přehledný, provedení ale zabere relativně více času.

Procedurální programování „míchá“ data a metody, je méně přehledné, ale má relativně rychlejší běh. (více v PPA2)

Příklad (Kruh) – ilustrace obou forem programování

Vytvoříme dva kruhy a napíšeme další metodu, která spočte rozdíl ploch obou kruhů.

StringBuffer s = new StringBuffer(koniklec);

System.out.println("Character.isDigit(s.charAt(0)): " + Character.isDigit(s.charAt(0)));

System.out.println("Character.isLetter: " + Character.isLetter(s.charAt(0)));

System.out.println("Character.isLetterOrDigit: " + Character.isLetterOrDigit(s.charAt(0)));

System.out.println("Character.isLowerCase: " + Character.isLowerCase(s.charAt(0)));

System.out.println("Character.isUpperCase: " + Character.isUpperCase(s.charAt(0)));

System.out.println("Character.isWhitespace: " + Character.isWhitespace(s.charAt(0)));

Page 35: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 35 (celkem 37)

Procedurálně: Počítáme rozdíl dvou ploch.

Objektově:

Počítáme rozdíl plochy kruhu referencovaného, tj. „našeho“ (this) objektu - vůči ploše kruhu jiného objektu, který je předán skutečným parametrem v metodě.

public class SpoctiRozdilPlochProc { static double spoctiPlochu(double polomer){ return polomer*polomer*Math.PI; }

static double spoctiRozdilPloch(double polomer1, double polomer2){

return Math.abs(spoctiPlochu(polomer1)-spoctiPlochu(polomer2)); }

public static void main(String[] args) {

double polomer1 = 10.0; double polomer2 = 1; System.out.println(spoctiPlochu(polomer1)); System.out.println(spoctiPlochu(polomer2)); System.out.println("Rozdil ploch: " + spoctiRozdilPloch (polomer1, polomer2));

} } 314.1592653589793

3.141592653589793 Rozdil ploch: 311.01767270538954

Page 36: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 36 (celkem 37)

class Kruh { private double polomer; public Kruh() { polomer = 1.0; } public Kruh(double polomer) { setPolomer(polomer); } public double getPolomer() { return polomer; } public void setPolomer(double polomer) { if(polomer > 0){ this.polomer = polomer; } } public double spoctiPlochu(){ return polomer*polomer*Math.PI; } public double spoctiRozdilPloch(Kruh k) { return Math.abs(this.spoctiPlochu() - k.spoctiPlochu()); } public String toString() { return "<Kruh: polomer = " + polomer + ", plocha = " + spoctiPlochu() + ">"; } }

public class SpoctiRozdilPlochObj { public static void main(String[] args) { Kruh kruh = new Kruh(10.0); Kruh krouzek = new Kruh(); System.out.println(kruh); System.out.println(krouzek); System.out.println("Rozdil ploch: " + kruh.spoctiRozdilPloch(krouzek)); } } <Kruh: polomer = 10.0, plocha = 314.1592653589793>

<Kruh: polomer = 1.0, plocha = 3.141592653589793> Rozdil ploch: 311.01767270538954

Page 37: Obsah 6. přednášky - zcu.cznetrvalo/vyuka/ppa1/portal/prednasky/... · 2016. 11. 2. · Přednášky KIV/PPA1, A. Netrvalová, 2016 6. přednáška Obsah 6. přednášky: Třídy

Strana 37 (celkem 37)

Další jednoduché úložky:

1. Vytvořte program, který bude fungovat jako kodér a

dekodér pro znaky Morseovy abecedy.

2. Celé číslo nazveme super číslem, jestliže ho

můžeme vyjádřit jako součet dvou čtverců nebo

jako podíl dvou čtverců. Napište program, který

ověří, zda číslo je či není super číslem, víte-li, že

např. rok 1914 nebyl super rokem!