Obsah
Kroky řešení problému na počítači - pár slov o SW inženýrství
Organizace javových pg. - třídy, balíky
„Objektovost“: zapouzření, dědičnost
Modifikátory přístupu k proměnným, metodám, třídám
Deklarace import
V tomto předmětu nás z toho bude zajímat jen něco a jen částečně:
Specifikace (tj. zadání a jeho formalizace)
Vývoj (tj. návrh a vlastní programování)
částečně Validace (z ní především testování)
Specifikace SW: Je třeba definovat funkcionalitu SW a operační omezení.
Vývoj SW: Je třeba vytvořit SW, který splňuje požadavky kladené ve specifikaci.
Validace SW: SW musí být validován („kolaudován“), aby bylo potvrzeno, že řeší právě to, co požaduje uživatel.
Evoluce SW: SW musí být dále rozvíjen, aby vyhověl měnícím se požadavkům zákazníka.
Tyto generické modely jsou dále rozpracovávány do podoby konkrétních metodik.
Metodika (tvorby SW) je ucelený soubor inženýrských postupů, jak řízeným způsobem, s odhadnutelnou spotřebou zdrojů dospět k použitelnému SW produktu.
Co bude odlišné oproti dosavadním programátorským zkušenostem?
program měl jeden nebo více zdrojových souborů (soubor = modul) tvořenými jednotlivými procedurami/fcemi, definicemi a deklaracemi (typů, proměnných...)
(a některé další OO jazyky): program je obvykle tvořen více soubory (soubor = popis jedné třídy) tvořenými deklaracemi metod a proměnných (případně dalších prvků) těchto tříd.
v Javě je nezbytná - zdrojové soubory organizujeme podle toho, ve kterých balících jsou třídy zařazeny
Zjistíme, jaké typy objektů se ve zkoumaném výseku reality vyskytují a které potřebujeme
Soubor Zivocich.java bude obsahovat (pozor na velká/malá písmena - v obsahu i názvu souboru):
public class Zivocich {
... popis vlastností (proměnných, metod...) živočicha ...
}
public značí, že třída je "veřejně" použitelná, tj. i mimo balík
Balíky obvykle organizujeme do hierarchií, např.:
třídy "dceřinného" balíku (např. svet.chovatelstvi.psi)
byly zároveň třídami balíku "rodičovského" (svet.chovatelstvi)!!!
Hierarchie balíků má tedy význam spíše pro srozumitelnost a logické členění.
Deklarujeme ji syntaxí: package názevbalíku;
Uvádíme obvykle jako první deklaraci v zdrojovém souboru;
Příslušnost k balíku musíme současně potvrdit správným umístěním zdrojového souboru do adresářové struktury;
např. zdrojový soubor třídy Pes umístíme do podadresáře svet\chovatelstvi\psi
Neuvedeme-li příslušnost k balíku, stane se třída součástí implicitního balíku - to však nelze pro jakékoli větší a/nebo znovupoužívané třídy či dokonce programy doporučit a zde nebude tolerováno!
V realitě jsme často svědci toho, že třídy jsou podtřídami jiných:
tj. všechny objekty podtřídy jsou zároveň objekty nadtřídy, např. každý objekt typu (třídy) ChovatelPsu je současně typu Clovek nebo
např. každý objekt typu (třídy) Pes je současně typu DomaciZvire (alespoň v našem výseku reality - existují i psi "nedomácí"...)
Podtřída je tedy "zjemněním" nadtřídy:
V Javě je každá uživatelem definovaná třída potomkem nějaké jiné - neuvedeme-li předka explicitně, je předkem vestavěná třída Object
Nadtřídě (superclass) se také říká "(bezprostřední) předek", "rodičovská třída"
Podtřídě (subclass) se také říká "(bezprostřední) potomek", "dceřinná třída"
Dědění může mít i více "generací", např.
Zivocich <- Clovek <- Chovatel (živočich je rodičovskou třídou člověka, ten je rodičovskou třídou chovatele)
Přeneseně tedy předkem (nikoli bezprostředním) chovatele je živočich.
public class Clovek extends Zivocich {
... popis vlastností (proměnných, metod...) člověka navíc oproti živočichovi ...
}
Deklarace import nesouvisí s děděním, ale s organizací tříd programu do balíků:
Pak lze používat všechny třídy z uvedeného balíku
Jak víme, třídy popisují skupiny objektů podobných vlastností
Třídy mohou mít tyto skupiny vlastností:
Vlastnosti jsou ve třídě "schované", tzv. zapouzdřené (encapsulated)
Třída připomíná pascalský záznam (record), ten však zapouzdřuje jen proměnné, nikoli metody.
Dědičnost (alespoň v javovém smyslu) znamená, že dceřinná třída (podtřída, potomek)
Zdokonalíme náš příklad s účtem tak, aby si účet "hlídal", kolik se z něj převádí peněz
Zdokonalenou verzi třídy Ucetnazveme KontokorentniUcet
Příklad 1.1. Příklad kompletního zdrojového kódu třídy
public class KontokorentniUcet extends Ucet {
// double zustatek; znovu neuvádíme
// ... zdědí se z nadtřídy/předka "Ucet"
// kolik mohu "jít do mínusu"
double povolenyKontokorent;
public void pridej(double castka) {
if (zustatek + povolenyKontokorent + castka >= 0) {
// zavoláme původní "neopatrnou" metodu
super.pridej(castka);
} else {
System.err.println("Nelze odebrat částku " + (-castka));
}
}
// public void vypisZustatek() ... zdědí se
// public void prevedNa(Ucet u, double castka) ... zdědí se
// ... předpokládejme, že v třídě "Ucet" používáme variantu:
// pridej(-castka);
// u.pridej(castka);
// } }
Vzorový zdroják sám o sobě nepůjde přeložit, protože nemáme třídu, na níž závisí. Celý kód vystavím až po kontrole příslušných úloh.
Klíčové slovo extends - značí, že třída KontokorentniUcet je potomkem/podtřídou/rozšířením/dceřinnou třídou (subclass) třídy Ucet.
Konstrukce super.metoda(...); značí, že je volána metoda rodičovské třídy/předka/nadtřídy (superclass). Kdyby se nevolala překrytá metoda, super by se neuvádělo.
Větvení if() {...} else {...} - složené závorky se používají k uzavření příkazů do sekvence - ve smyslu pascalského begin/end.
Přístup ke třídám i jejim prvkům lze (podobně jako např. v C++) regulovat:
Omezení přístupu je kontrolováno hned při překladu -> není-li přístup povolen, nelze program ani přeložit.
Tímto způsobem lze regulovat přístup staticky, mezi celými třídami, nikoli pro jednotlivé objekty
Jiný způsob zabezpečení představuje tzv. security manager, který lze aktivovat při spuštění JVM.
Přístup je v Javě regulován jednotlivě po prvcích
Omezení přístupu je určeno uvedením jednoho z tzv. modifikátoru přístupu (access modifier) nebo naopak neuvedením žádného.
protected => přístupné jen z podtříd a ze tříd stejného balíku
public class Ucet {
// chráněná proměnná
protected float povolenyKontokorent;
}
používá se jak pro metody (velmi často), tak pro proměnné (méně často)
lokální v balíku = přátelský=> přístupné jenze tříd stejného balíku,už ale ne z podtříd, jsou-li v jiném balíku
public class Ucet {
Date created; // přátelská proměnná
}
používá se spíše u proměnných než metod, ale dost často se vyskytuje z lenosti programátora, kterému se nechce psát protected
osobně moc nedoporučuji, protože svazuje přístupová práva s organizací do balíků (-> a ta se může přece jen měnit častěji než např. vztah nadtřída-podtřída.)
Mohlo by mít význam, je-li práce rozdělena na více lidí na jednom balíku pracuje jen jeden člověk - pak si může přátelským přístupem chránit své neveřejné prvky/třídy -> nesmí ovšem nikdo jiný chtít mé třídy rozšiřovat a používat přitom přátelské prvky.
Používá se relativně často pro neveřejné třídy definované v jednom zdrojovém souboru se třídou veřejnou.
private => přístupné jen v rámci třídy, ani v podtřídách - používá se častěji pro proměnné než metody
označením private prvekzneviditelníme i případným podtřídám!
public class Ucet {
private String majitel;
...
}
Nastavení přístupových práv k třídě pomocí modifikátorů se děje na úrovni tříd, tj. vztahuje se pak na všechny objekty příslušné třídy i na její statické vlastnosti (proměnné, metody) atd.
Nastavení musí vycházet z povahy dotyčné proměnné či metody.
Nevíme-li si rady, jaká práva přidělit, řídíme se následujícím:
metoda by měla být public, je-li užitečná i mimo třídu či balík - "navenek"
jinak protected
máme-li záruku, že metoda bude v případných podtřídách nepotřebná, může být private - ale kdy tu záruku máme???
proměnná by měla být private, nebo protected, je-li potřeba přímý přístup v podtřídě
téměř nikdy bychom neměli deklarovat proměnné jako public!
Třídy deklarované jako veřejné (public) musí být umístěné do souborů s názvem totožným s názvem třídy (+přípona .java) i na systémech Windows (vč. velikosti písmen)
kromě takové třídy však může být v tomtéž souboru i libovolný počet deklarací neveřejných tříd
private nemají význam, ale přátelské ano