36 - Objektová orientace
rozšiřuje modulární jazyky jazyky o možnost spojit konkrétní data s operacemi
využívá dekompozici do modulů - tvoří samostatné celky, které tvoří objektově orientovaný systém
hlavní 3 výhody objektové orientace:
analogie mezi softwarovým modelem a reálným modelem
flexibilita takovýchto softwarových modelů
jejich znovupoužitelnost
OO jazyky: Simula 67, Smalltalk 72 a 80, C++, Java, C#,
PHP, Python, Lisp, …
čistě objektové jazyky - Smalltalk, Ruby, Python
hybridni jazyky - objektově orientované - založeny na imperativním progragramování, částečně implementují vlastnosti objektového programování - C++, Java
mají základní kořenovou třídu (Java - třída Object)
nemají základní třídu (C++)
objektové rozšíření původně neobjektových jazyků - Object Pascal
Základní pojmy
1. Objekt
Identita vs. Shoda
2. Abstrakce
schopnost programu zjednodušit některé aspekty informací / vlastnosti objektů, se kterými program pracuje
černá skříňka - pracujeme s ní pomocí definovaného rozhraní, ale už nás nezajímá, jak byla vytvořena a co je v ní
variant/invariant - část programu, kde se hodnoty proměnných mění/nemění při opakovaném průchodu této časti kódu
Modifikátory viditelnosti
mechanismus, kterým se dá docílit definování, které metody a proměnné budou komu přístupné
tímto mechanismem podrobněji konfigurujeme koncept zapouzdření
podle jazyka UML známe tři základní modifikátory
soukromý (private
) - přístupné pouze z metod stejné třídy
chráněný (protected
) - přístupné pouze ze stejné třídy + tříd odděděných
veřejný (public
) - dostupné všude
existují i další internal, friend, …
3. Zapouzdření
souvisí s abstrakcí
uživatel nemůže měnit interní stav objektů libovolným (tedy i neočekávaným) způsobem, ale musí k tomu využívat poskytované rozhraní (operace nad objektem)
každý objekt má protokol, který definuje, jak komunikovat s objektem
4. Polymorfismus
mnohotvárnost
reakce na stejnou zprávu se liší v závislosti na objektu, kterému byla zaslána
využívá se u rozhraní (Interface), kde více tříd implementuje jedno rozhraní
například mějme Interface Tvar
, který deklaruje metodu vypocitejObsah()
⇒ dále si pak vytvoříme jednotlivé tvary - Ctverec
a Obdelnik
, ktere budou implementovat nase rozhrani Tvar
⇒ tedy musi definovat vsechny metody, ktere nase rozhrani obsahuje ⇒ v nasem pripade metodu vypocitejObsah()
, ktera se bude list v zavislosti na zvolenem tvaru
Přetěžování metod
například nase třída Obdelnik
by mohla mít hned několik konstruktorů:
> public Obdelnik() - vytvoří defaultní obdélník například o velikosti stran a=4, b=5 jednotek
> public Obdelnik(int a, int b) - vytvoří obdélník o zadaných velikostech
> public Obdelnik(Point bod) - vytvoří obdélník o velikostech definových v jiné třídě
Přetěžování operátorů
například operátor + může sečíst dvě čísla, může konkatenovat dva řetězce, může sečíst jednotlivé položky dvou asociativních polí
Časná a pozdní vazba
při překladu nemusí být zřejmé díky polymorfismu s jakým typem objektu budeme pracovat ⇒ časná/statická vazba
⇒ to může mít za následek, že nemusíme zvolit správnou metodu (pracujeme s objekty na abstraktní úrovni)
⇒ je třeba identifikovat potřebnou metodu až za běhu programu, kdy je nutné ji invokovat ⇒ pozdní/dynamická vazba
⇒ k implementaci se používají VMT - tabulky virtuálních metod ⇒ každá instance třídy, která obsahuje virtuální metody, obsahujeodkaz do VMT
⇒ VMT obsahuje ukazatele na konkrétní metody, které jsou pro daný typ platné
u dynamický typovaných OO jazyků jsou všechny metody virtuální
5. Dědičnost
způsob, jak implementovat sdílené chování
v případech, kdy chceme rozšířit nějakou třídu o dané vlastnosti
reflexivní, tranzitivní (dědí hierarchicky všechny třídy) a antisymetrická relace
jako příklad jde uvést třída Hráč, která má vlastnosti, jméno, příjmení, věk ⇒ existují ovšem různé typy hráčů, jako je útočník, obránce, brankář ⇒ u každého si budeme ovšem chtít pamatovat jiné vlastnosti (střelené góly vs. zákroky) ⇒ proto vytvoříme dané třídy rozšířením základní třídy hráč ⇒ třídy budou sdílet pouze atributy z rozšiřované třídy
metoda/klíčové slovo super
⇒ požívá se např. v konstruktoru více specifické třídy, kdy se odkazujeme na třídu, z které dědí (voláme konstruktor děděné třídy)
typy dědičnosti:
vícenásobná
jednoduchá
možnost dědit pouze jednu třídu
řeší problém konfliktů jmen
nemožnost dědičnosti více tříd se zajistí pomocí implementace rozhraní, kde počet není omezen
Java
co dědíme:
dědičnost implementace (Java - extends
) - rozšíření třídy ⇒ přebíráme už nadefinované metody
dědičnost rozhraní (Java - implements
) - nutí nás implementovat dané metody
redefinice metody - přepsání třídy - viz. polymorfismus
Rozhraní
schéma, které deklaruje seznam metod (jména, parametry, návratové typy)
použití rozhraní na jistou třídu pak vynucuje implementaci všech metod uvedených v rozhraní ⇒ rozhraní nám může vynutit, co je třeba naimplementovat
každé třídě uvést několik rozhraní
Datové a řídící abstrakce
1. Třídně orientované jazyky
Instanciace objektů
metod ⇒ inicializuje datové položky objektu
vytváření kopií objektů:
hluboká - kromě objektu samotného jsou kopírovány i obkekty, které instanční proměnné objektu referencují
mělká - hluboká kopie hloubky 0 - kopíruje jenom objekt samotný
Destrukce objektů
Static
2. Prototypově orientované jazyky
-
znají pouze jediný typ objektů a nevyčleňují objekty, které by reprezentovaly nějakou třídu
nerozlišuje se mezi entitami a třídami (Static)
jsou pouze objekty, které obsahují členské proměnné a metody ⇒ tyto složky se nazývají Sloty
pokud je objektu poslaná zpráva, prozkoumá množinu svých slotů
nové objekty se vytváří mělkým kopírováním již existujících (klonováním)
objekty mohou obsahovat rodičovské sloty
ukazatele na objekt, z kterých byly vytvořeny
při volání metody objekt nejprve projde své sloty a pokud nenajde, odkáže se přes rodičovský slot na rodičovský objekt (delegace) ⇒ po nalezení slotu (metody) je spuštěn kód ⇒ jako příjemce je označen objekt, který delegaci provedl
třídy se sdíleným chováním lze nahradit rysy
objekty, které obsahují pouze metody
nové objekty mají v rodičovském slotu ukazatele na rys
provázáním rysů lze řešit dědičnost (některé jazyky umožňují mít více rodičovských slotů)
jelikož sloty jde dynamicky měnit, lze dosáhnout dynamické dědičnosti
k plnému nahrazení tříd nám ovšem rysy nestačí - je třeba zavést prototypy
řeší problém instančních proměnných, kde každý objekt musí mít jejich samotnou kopii
rys je doplněn objektem (šablonou), který:
obsahuje sloty instančních proměnných s defaultními hodnotami
ve svém rodičovském slotu odkazuje daný rys
nová instance se vytvoří nakopírováním dané šablony (viz obrázek)
jazyk SELF (1986) - dialekt Smalltalku založený na prototypech
JavaScript - od SELFu se značně odlišuje
vhodné pro názorné a vizuální modelování, prototypování a programování
nevýhoda jazyků - vyšší režie
<if-stmt>
::= if <condition> then <stmts> <else-if>
<else-if>
::= endif ;
| else <stmts> endif ;
| <elsif> <else-if>
ς-kalkul
UML
další možný formalismus
grafický jazyk
-
Překlad
ukládá popis každé třídy do speciálního prostoru
vytváří graf závislostí jednotlivých tříd a poté je lineárně uspořádává ⇒ na to nemusí stačit jeden průchod
náročná je práce s jmennými prostory a modifikátory viditelnosti
fáze:
-
sémantická analýza - oproti modulárním jazykům mnohem náročnější
interpret
Výhody a nevýhody
+
vyšší míra abstrakce
jednodušší dekompozice problému
přirozenější práce (modelujeme reálné objekty)
udržovatelnost a rozšiřitelnost
znovupoužitelnost
-
v některých oblastech neexistuje analogie s reálnými objekty a pak je obtížné určit a definovat intuitivně ty softwarové
složitější sémantika - více času na naučení
-
výsledný generovaný kód je pomalejší
režie na uložení objektů v paměti (např. odkaz na třídu objektu)
Zdroj
Při tvorbě tohoto tématu jsem čerpar především z
druhých skript IPP. Snažil jsem se udělat co nejpřehlednější výtah pro rychlé učení.
Potvrzení
36 |
Celé jméno | OK | !!! |
Jirka Hynek | | |
vagy | | |
Tom Ofeig | | |
| 3 | |
Diskuze
Dodělána kapitola Překladače na přání Honzy.
Btw… k tomu přetěžování operátorů, jak jsme se dohadovali na srazu:
Přetěžování operátorů v Javě není.
Operátor == porovnává, jestli dvě reference jsou na stejný objekt.
Výsledek: Nejsou stejne
Nemá to nic společného s equals(), které slouží k porovnávání obsahu. Přetěžuje se v případě, že si vytvoříme vlastní objekt s vlastními pravidly porovnávání.
Výsledek: Jsou stejne … protože to porovnává obsah … pokud bych si vytvořil vlastni String, mohl bych si nadefinovat vlastní equals, že bych třeba řekl, že ahoj je stejný s reverzním joha, kdybych ale použil opět == , porovnávalo by to opět reference…
Dobry priklad. Tezko uverit, ze jsme to probirali vic jak pred mesicem
Chybí návrhové vzory: singleton, abstraktní továrna, iterátor, dekorátor
„rodicovsky slot=ukazatele na objekt, z kterých byly vytvořeny“
Odkial berete tuti hovadinu nechapem sak sa pozrite na tu ukazku so selfu…