(základní pojmy OOP, zapouzdření, dědičnost, polymorfizmus, objektové programování v imperativním jazyce, spolupráce objektů. Událostmi řízené programování. Výjimky)
Objektově orientované programování je metoda vytváření software. OOP vzniklo v 70. letech 20. století, oproti strukturovanému programování nedekomponuje problém shora dolů (rozdělení na menší celky, viz ap3), ale vytváří stavební objekty, pomocí nichž se program modeluje (styl zdola nahoru). Lépe odpovídá uspořádání skutečného světa. Mezi OO programovací jazyky patří Smalltalk, C++, Java, Python apod.
Objekt - má svůj obraz v reálném světě, má vlastnosti a chování reprezentovány atributy a metodami. Objekt navenek zpřístupňuje rozhraní, pomocí kterého se s objektem pracuje. Veřejné rozhraní objektu je dáno veřejnými metodami objektu.
Třída je typ objektu, instance je konkrétní výskyt objektu. Příklad ukazuje vytvoření instance třídy Person:
Person kuba = new Person("Kuba"); //novy objekt kuba je instanci tridy Person
Když je objekt vytvářen, volá se také automaticky speciální funkce třídy nazývaná konstruktor (užívaná k inicializaci členů třídy).
Jednotlivé Atributy a metody jsou vlastnosti instancí objektu, nikoliv tříd.
kuba.name //atribut instance uchovavajici jmeno kuba.getName() //metoda vracejici jmeno
Speciálním případem třídy je abstraktní třída. Je to třída která obsahuje nejméně jednu abstraktní metodu a z této abstraktní třídy není dovoleno vytvářet instance. Teprve třída, která je jejím potomkem (viz dále) a implementuje všechny abstraktní metody, může vytvářet instance. Neabstraktní metody abstraktní třídy jsou společné všem potomkům.
public abstract class SqlOperations { abstract void sqlConnect(); //tato metoda bude rozdilna pro Oracle, MySQL... } public class MySqlOperations extends SqlOperations{ void sqlConnect() { //implementace podle potreby } }
Interface (rozhraní) je množina hlaviček metod, které mohou být implementovány třídou. Pokud třída implementuje rozhraní, musí doimplementovat všechny jeho metody. Pokud tedy existuje rozhraní
public interface ElectricalDevice { public void switchOn(); public void switchOff(); }
a nějaká třída jej implementuje, můžeme si být jisti, že instance dotyčné třídy obsahují metody switchOn() a switchOff(). V C++ interface není.
if (microwave instanceof ElectricalDevice) { //trida Microwave implementuje ElectricalDevice microwave.switchOn(); }
V některých jazycích (Java, platforma .NET) se automaticky stará o destrukci nepotřebných objektů garbage collector. Objekty jsou rušeny, jakmile na něj neexistuje žádný odkaz (např. při konci bloku, kde byl objekt definován, nebo přiřazením hodnoty odpovídající null). Při zániku objektu je volána automaticky speciální funkce destruktor.
Objektové programování je charakterizováno především následujícími koncepty:
Atributy by měly být privátní (jinak porušení zapouzdření), přístup k nim by měl být povolen pouze přes metody (viz Spolupráce objektů). Příklad:
public class Person(){ private String personName; public void changePersonName(String newName){ //tato metoda umoznuje kontrolu jmena pred jejim prirazenim atributu //k samotne personName neni z vnejsku tridy pristup if (allowNewName(newName)) { personName = newName; } } }
Dědičnost odpovídá vztahu generalizace specializace (automobil → nákladní automobil lze dědit, protože nákladní automobil je speciální případ automobilu, ovšem bod → bod+poloměr dědit nelze, protože kruh není speciální případ bodu). V Javě je možné, aby třída byla přímým potomkem pouze jedné třídy.
Obecně rozlišujeme 3 druhy polymorfismu
abstract class Zvire(){ public Zvire(){} abstract void makeNoise(); public void runAway(){ System.out.print("Zvire utika pryc."); } } public class Kocka() extends Zvire{ //Kocka dědí metody třídy Zvire, jde o dedičnost public Kocka(){ } public void makeNoise(){//**(1)** System.out.print("Mnau mnau."); } } public class Ptak() extends Zvire{ public Ptak(){} public void makeNoise(){//**(1)** System.out.print("Pip pip."); } @Override public void runAway(){ //**(2)** System.out.print("Zvire odletlo pryc."); } public makeNoise(string zvuk){ //**(3)** System.out.print("Pip pip."+zvuk); } public makeNoise(int times){ //**(3)** System.out.print("Pip pip "+times.toString()+" krát"); } }
Pokud objekty implementují rozhraní, tak z vnějšku s tímto objektem komunikují ostatní objekty pomocí rozhraní.
Spolupráce objektů je úzce svázaná s Objektově orientovaným návrhem. V návrhu se definují vazby mezi jednotlivými třídami, tj. volání metod mezi třídami, přistupování k atributům tříd atd. Pokud je dobře provedený návrh, tak je možné z tohoto návrhu rovnou vygenerovat balíčky, rozhraní a třídy včetně metod a atributů a programátor pak jen naimplementuje jednotlivé metody.
Funguje to podobně jako volání metod v rámci jedné třídy - vytvoříme si instanci třídy (nebo použijeme vhodnou existující), zavoláme metodu a dostaneme návratovou hodnotu(pokud je void, tak jen provede kód a nevrátí nic). Samozřejmě je třeba myslet i na výjimky.
Většina jazyků již má hotové nejrůznější balíčky objektů, které můžeme použít při běžné práci - například při komunikaci s databází, tvorbu GUI atd.
Reagují na chybu. Měly by se používat výhradně k ošetření výjimečných situací, nejsou standardní prostředek řízení programu. V Javě se výjimky dědí stejně jako ostatní třídy, programátor může vytvářet vlastní.
Rozlišují se hlídané a nehlídané výjimky:
* Hlídaná výjimka - pokud může vzniknout, musíme na ni zareagovat, reagují na věc, kterou programátor nemůže ovlivnit, chybu okolního prostředí. V Javě potomci třídy Exception. Příklady:
IOException, CertificateExpiredException...
* Nehlídaná výjimka - taktéž běhová, runtime výjimka. Označují chybu vzniklou kdekoliv v kódu, reagují na chybu programátora (i v případě nekontrolování vstupu uživatele). Typicky se z nich nelze zotavit. V Javě potomci třídy RuntimeException. Příklady:
IllegalArgumentException, NullPointerException, IndexOutOfBoundsException...
Při výjimce může program skončit, pokusit se z výjimky zotavit, poslat ji volající funkci, vyhodit jinou výjimku (třeba více obecnou).
Ošetření výjimky:
try { //hlidany blok } catch (TypVyjimkyException promennaVyjimky) { //osetreni vyjimky } catch (ObecnejsiTypVyjimkyException promennaVyjimky) { //osetreni vyjimky. specialnejsi predchazi obecnejsi } finally { //v C++ finally neni //blok provedeny at je vyjimka vyhozena nebo ne //typicky zavreni otevreneho souboru, ukonceni sitoveho spojeni... //vyse zminene by klidne mohlo byt realizovano i v catchi, ale //finally slouzi spise k osetreni predcasneho ukonceni behu (return;) v try bloku }
Propagace výjimky: k ošetření dojde o jednu nebo více úrovní výše
public class Evil{ public static void main(String[] args) { try { DoEvilWithFive(); } catch(Exception e) { //zachytí obecnou vyjímku System.out.println("You are such an evil man."); } } public void DoEvilWithFive() throws DivideByZeroException{ this.doEvil(5); //vyhodí vyjímku která je vypropagována do main } public void doEvil(int number) throws DivideByZeroException{ int evil; evil = number/0; //vyhodí vyjímku dělení nulou, která je vypropagována do metody DoEvilWithFive() } }
Základní princip reakce objektového programu na vnější akci. Používá se např. u programů s GUI – běh programu je řízen událostmi.
Objekty GUI mají nadefinovány události (eventy; např. onClick, onMouseOut, onLoad, onClose…) a programátor k nim programuje metody – eventListenery – obsahující příkazy (např. volání privátních metod) které na událost reagují.
Události však nejsou pouze u objektů GUI, používají se u veškerých objektů, kde může vzniknout událost (object.onUnload, timer.onTimeout, http.onResponse, thread.onDispose…). Událostmi řízené programování bývá vícevláknové, ale většinou spouštění vláken řídí běhové prostředí a my se o vlákna starat nemusíme. Existují ale případy, kdy je vhodné si separátní vlákna spustit samostatně (např. z důvodu využití výkonu vícejádrových procesorů).
//kód je v C# public class GUI: Form { private Button tlacitko; private void GUI(){ this.tlacitko = new Button(); this.tlacitko.Text = "Spusť poplach"; this.tlacitko.Click += new System.EventHandler(this.tlacitko_Click_Handler); } private void tlacitko_Click_Handler(object sender, EventArgs e){ MessageBox.Show("Poplach, poplach, poplach"); } }
Každý z těchto jazyků vzniknul za jiným účelem - C++ jako objektová verze nízkoúrovňového jazyka C, Java jako abstrahovaná od platformy pomocí Java Virtual Machine. Několik důležitých rozdílů mezi těmito jazyky:
C++:
Java
C#
//kód je v C# public class test { private string attribute = null; //nastavovani vnitrni hodnoty attribute (get a set muzou obsahovat libovony kod) public string ManualProperty { get { return attribute; } set { attribute = value; } } //vyse uvedeny kod bez pouziti vnitrni promenne public string AutomaticProperty { get; set; } }
Kuba Talaš (icq 257208851)
Vesměs hotovo, případně se vyjádřete v diskuzi nebo přímo upravte wikistránku.
Iniciativě se meze nekladou ;)