Maturitní otázka č. 22 - objektově orientované programování

Na příkladech popište základní koncepce objektově orientovaného programování

Objektově orientované programování přináší oproti obyčejnému procedurálnímu programování především nový úhel pohledu. Samotné prostředky programovacího jazyka, které nám umožňují jednoduše s objekty pracovat, jsou až druhý krok k našemu programátorskému pohodlí. Při troše pečlivosti bychom mohli programovat objektově i v jazycích, které to přímo neumožňují (jako je C a Pascal) a pojem "objekt" v nich neexistuje. Důležitější je návrh kódu. Když se budeme ke strukturovaným datovým typům chovat jako k objektům a ovládat je pouze prostřednictvím nějakých obslužných funkcí, můžeme svůj přístup prohlásit za objektový.

Ale přece tedy: základním pojmem je objekt. To je jakýsi balík proměnných a obslužných funkcí, které s proměnnými pracují. Těmto proměnným budeme říkat vlastnosti (někdy též atributy) a funkcím určitého objektu budeme říkat metody. Sdružujeme je pohromadě tak, aby z lidského hlediska doopravdy připomínaly nějaký předmět. Metody nám navenek nabízejí možnosti, co můžeme s tímto předmětem - objektem - dělat.

Objekt má navíc dvě zvláštní metody. Konstruktor je metoda, která se zaručeně zavolá při vytváření objektu v programu. Například, pokud máme objekt pro soubor na disku, konstruktor patrně dostane zadaný název souboru a rovnou jej otevře, abychom se souborem pak mohli v program pracovat. Kdyby existoval takový objekt bez otevřeného souboru, mohl by program například při pokusu o čtení spadnout; proto nám programovací jazyk zaručuje, že se konstruktor na každém vytvořeném objektu spustí. Zbývá samozřejmě na nás, ujistit se v konstruktoru, že se objekt vytvoří správně, v tomto případě ověřit, že se soubor otevřel.

Naopak, destruktor je metoda, která se spustí, když objekt mažeme. V některých jazycích o to musíme požádat, v Javě destruktory pořádně nejsou a v Ruby se s nimi pracuje těžko, naopak například v Pythonu se volají zaručeně a automaticky.

Vysvětlete pojmy třída, objekt, dědičnost, zapouzdření, polymorfismus

Třída je předpis, podle kterého objekty vytváříme. Ve třídě jsou definované metody a vlastosti, které budou všechny objekty mít.

Objekt je konkrétní proměnná vytvořená podle nějaké třídy; jeho datový typ je právě ta třída. Objekt v sobě má uložené hodnoty svých vlastností, ale jejich názvy má společné se všemi ostatními objekty stejné třídy. Říkáme také, že objekt je instancí určité třídy.

Zapouzdření nás nutí s objekty určité třídy zacházet správně. Abychom se drželi objektového návrhu, zapouzdřením je možné některé vlastosti a metody úplně skrýt před ostatním kódem; pak bude možné s nimi pracovat jen pomocí jiných metod. Obvykle rozlišujeme tři druhy zapouzdření:

Jedna třída může dědit od druhé; získá tím po svém předkovi všechny vlastnosti a metody. Může k tomu přidat nějaké další, či zděděným názvům přiřadit něco jiného. Může se stát, že metoda potomka dělá něco jiného, přestože se jmenuje stejně jako u předka. Je možné, aby od jednoho předka dědilo víc potomků naráz. V některých jazycích je možné i to, aby jedna třída dědila od více různých potomků - je ale trochu těžké si rozmyslet, co vlastně chceme, aby se v takovém případě stalo.

Dědění má výhodu, že všichni potomci získali po svém předkovi něco společného. Pokud předek má určitou vlastnost, můžeme si být jisti, že ji mají všichni potomci, nezávisle na tom, co je to konkrétně za typy. Polymorfismus nám umožňuje se všemi různými potomky zacházet jako s jejich společným předkem (dokud nás zajímají jen vlastosti jejich předka). Typicky, pokud třída Potomek dědí od třídy Předek a v kódu máme nějakou funkci, která chce jako parametr objekt typu Předek, můžeme jí vrazit i jakýkoliv objekt typu Potomek. Situace se mírně komplikuje, pokud Potomek má metodu se jménem stejným jako u předka, která ale dělá něco jiného - různé programovací jazyky se liší v tom, která z metod se v takovém případě na objekt zavolá.

Například, můžeme mít třídu Ovoce, která má vlastnosti barva a váha, a třídu Mandarinka, která od ní dědí. Mandarinka bude mít navíc pravdivostní vlastnost s_peckama a bude mít jiný konstruktor než Ovoce, protože musí nastavit barvu vždy na oranžovou. Když pak máme jinde v kódu objekt typu Váha s metodou Váha.zvaž(Ovoce), můžeme mu rovnou předat Mandarinku; v tom není problém, každé Ovoce se dá zvážit.

Poznámka na konec: třída obvykle za běhu programu obsahuje kód metod (protože ten bude společný všem jejím instancím - objektům, nemá smysl jej kopírovat), ale žádnou z vlastností (ty naopak musí každá instance mít své vlastní, nezávisle na ostatních). Jsou od toho ale výjimky; některé jazyky umožňují měnit metody tak, že každý objekt bude používat jinou, přestože všechny jsou instancemi stejné třídy - takovým metodám říkáme virtuální. Druhou výjimkou jsou statické vlastnosti, které se ukládají přímo ve třídě a všechny instance budou tedy za běhu programu pracovat se stejnou hodnotou; budou si ji moct měnit navzájem.