Objektově orientované programování

Z MiS
(Rozdíly mezi verzemi)
Přejít na: navigace, hledání
(Objekty, třídy: Doplněno podrobněji.)
(Drobné opravy, vzhled, dědičnost a spol. do vlastní stránky)
Řádka 76: Řádka 76:
  
 
; Dědičnost (''inheritance'')
 
; Dědičnost (''inheritance'')
*pokud objekt sdílí a rozšiřuje rozhraní jiného objektu, popisujeme to dědičností
+
* pokud objekt sdílí a rozšiřuje rozhraní jiného objektu, popisujeme to dědičností
 
* dědičnost používáme pouze tehdy, kdy objekt přebírá (a případně rozšiřuje o nové zprávy) CELÉ rozhraní jiného objektu (jinak používáme skládání + delegování)
 
* dědičnost používáme pouze tehdy, kdy objekt přebírá (a případně rozšiřuje o nové zprávy) CELÉ rozhraní jiného objektu (jinak používáme skládání + delegování)
 +
* potomek může zároveň kdykoli zastoupit předka
  
 
== Použití konstruktů OOP v programovacích jazycích ==
 
== Použití konstruktů OOP v programovacích jazycích ==
Řádka 85: Řádka 86:
 
=== Objekty, třídy ===
 
=== Objekty, třídy ===
 
*Každý objekt je instancí některé třídy
 
*Každý objekt je instancí některé třídy
*Často bývá jedna třída univerzální předek (například v Javě třída <code>Object</code>), ostatní třídy jsou pak potomky této třídy
+
*Často bývá jedna třída univerzální předek (například v Javě třída <code>Object</code>), ostatní třídy jsou pak potomky této třídy nebo potomky jejích potomků.
  
 
; Vytváření objektů (instancí třídy)
 
; Vytváření objektů (instancí třídy)
* Ve většině jazyků je operátor <code>new</code>.
+
* Ve většině jazyků se používá operátor <code>new</code>.
 
* Při vytváření instance se volá konstruktor, který inicializuje hodnoty atributů.
 
* Při vytváření instance se volá konstruktor, který inicializuje hodnoty atributů.
  
Řádka 96: Řádka 97:
 
* Pokud neuvedeme konstruktor, vytváří se obvykle tzv. „implicitní konstruktor“. Ten nastaví hodnoty proměnných na úvodní hodnoty podle jejich typu
 
* Pokud neuvedeme konstruktor, vytváří se obvykle tzv. „implicitní konstruktor“. Ten nastaví hodnoty proměnných na úvodní hodnoty podle jejich typu
  
=== Zprávy ===
+
=== Zprávy &rarr; metody ===
 
* Reakci objektu na zprávu popisují metody:
 
* Reakci objektu na zprávu popisují metody:
 
; Metoda má:
 
; Metoda má:
Řádka 104: Řádka 105:
 
; Přetěžování metod  (''overloading'')
 
; Přetěžování metod  (''overloading'')
 
*Jedna třída může mít více metod se stejným jménem.
 
*Jedna třída může mít více metod se stejným jménem.
*Metody se stejným jménem se musí lišit:
+
*Metody se stejným jménem se musí lišit počtem parametrů, [[Java: Datové typy|typem]] parametrů nebo obojím.
**počtem parametrů
+
**[[Java: Datové typy|typem]] parametrů
+
**(nebo obojím)
+
 
; Překrývání metod (''overlaying'')
 
; Překrývání metod (''overlaying'')
*souvisí s dědičností a polymorfismem
+
* souvisí s dědičností a polymorfismem
*potomek může na stejnou zprávu reagovat jinak, než předek
+
* potomek může na stejnou zprávu reagovat jinak, než předek
** pak říkáme, že metoda v potomkovi „překrývá“ metodu předka
+
* pak říkáme, že metoda v potomkovi „překrývá“ metodu předka
 
; Atomizace metod
 
; Atomizace metod
 
*metoda by měla řešit jednu konkrétní věc
 
*metoda by měla řešit jednu konkrétní věc
Řádka 117: Řádka 115:
 
*délka metody bez deklarace proměnných cca 5 řádků
 
*délka metody bez deklarace proměnných cca 5 řádků
  
=== Atributy ===
+
=== Atributy &rarr; proměnné ===
 
*Atributy jsou realizovány proměnnými.
 
*Atributy jsou realizovány proměnnými.
 
; Instanční proměnné
 
; Instanční proměnné
 
*Každá instance má svoji vlastní hodnotu.
 
*Každá instance má svoji vlastní hodnotu.
*:Například třída UcebniSkupina může mít atribut počet žáků (kteří do dané skupiny chodí). Odpovídající proměnná musí být instanční, protože každá učební skupina může mít jiný počet žáků. (Je to vlastnost konkrétní skupiny.)
+
<div class="Priklad">Například třída UcebniSkupina může mít atribut počet žáků (kteří do dané skupiny chodí). Odpovídající proměnná musí být instanční, protože každá učební skupina může mít jiný počet žáků. (Je to vlastnost konkrétní skupiny.)</div>
 
*Zabírají paměť tolikrát, kolik instancí třídy vytvoříme.
 
*Zabírají paměť tolikrát, kolik instancí třídy vytvoříme.
 
; Třídní proměnné
 
; Třídní proměnné
 
* klíčové slovo <code>static</code>
 
* klíčové slovo <code>static</code>
 
*Hodnota je společná pro všechny instance dané třídy.
 
*Hodnota je společná pro všechny instance dané třídy.
*:Například je-li maximální počet žáků v učební skupině dán zákonem (pro všechny učební skupiny stejný), pak tento atribut budeme realizovat třídní proměnnou třídy UcebniSkupina.
+
<div class="Priklad">Například je-li maximální počet žáků v učební skupině dán zákonem (pro všechny učební skupiny stejný), pak tento atribut budeme realizovat třídní proměnnou třídy UcebniSkupina.</div>
 
*Zabírají paměť jen jednou, bez ohledu na počet instancí.
 
*Zabírají paměť jen jednou, bez ohledu na počet instancí.
; Přístupnost metod a atributů (určena modifikátory)
+
 
* pouze ze tříd v jednom balíčku
+
=== Přístupnost metod a proměnných ===
* navíc z potomků třídy
+
* Metody a proměnné mohou být přístupné:
* z libovolné třídy
+
** pouze z dané třídy
Syntaxe v Javě viz [[Java: Modifikátory přístupu]].
+
** pouze ze tříd ve stejném balíčku
=== Dědičnost ===
+
** navíc z potomků třídy
*Klíčové slovo <code>extends</code>.
+
** z libovolné třídy
*Třída může mít pouze jednu rodičovskou třídu!
+
* Přístupnost určují obvykle modifikátory (viz syntaxe v Javě v [[Java: Modifikátory přístupu]]).
 +
 
 +
== Dědičnost ==
 +
* V mnoha jazycích se omezuje dědičnost na dědění maximálně z jedné třídy. Tím se vyhneme některým problémům při implementaci.
 +
 
 +
=== Zastupitelnost tříd ===
 +
* V jazycích, které vyžadují typovou kontrolu v době překladu, je často třeba předem uvést typ objektů, které budeme například vkládat do [[Java: Kontejnery|kontejneru]].
 +
* My ale často potřebujeme vkládat objekty různých tříd.
 +
* K řešení můžeme využít:
 +
** rozhraní
 +
** abstraktní třídy
 +
** dědičnost
 +
 
 
=== Abstraktní třída ===
 
=== Abstraktní třída ===
 
*Klíčové slovo <code>abstract</code>
 
*Klíčové slovo <code>abstract</code>
Řádka 143: Řádka 153:
 
*Těla abstraktních metod budou doplněna v potomcích třídy.
 
*Těla abstraktních metod budou doplněna v potomcích třídy.
 
*Nelze vytvořit instanci abstraktní třídy.
 
*Nelze vytvořit instanci abstraktní třídy.
 +
* Viz [[Java: Abstraktní třídy, dědičnost a rozhraní]].
 +
 
=== Rozhraní (interface) ===
 
=== Rozhraní (interface) ===
 
*„Čistě abstraktní třída“.
 
*„Čistě abstraktní třída“.
Řádka 152: Řádka 164:
 
Pokud implementujeme interface, pak „slibujeme“, že součástí rozhraní třídy jsou minimálně metody, zahrnuté v interface.
 
Pokud implementujeme interface, pak „slibujeme“, že součástí rozhraní třídy jsou minimálně metody, zahrnuté v interface.
 
</div>
 
</div>
 +
* Viz [[Java: Abstraktní třídy, dědičnost a rozhraní]]
 +
 +
<div class="Priklad">
 +
; Dědičnost × Skládání &mdash; Čítač příchodů
 +
* Představme si, že máme již vytvořenou třídu <code>Kalkulacka</code> s metodou <code>pricti(cislo)</code>.
 +
* Máme vytvořit třídu <code>CitacPrichodu</code>, která při každém průchodu dveřmi přičte do pomocné proměnné jedničku.
 +
* Napadne nás, že bychom mohli použít už fungující kód třídy <code>Kalkulacka</code>
 +
* Použijeme tedy instanci třídy <code>Kalkulacka</code> jako atribut třídy <code>CitacPrichodu</code>.
 +
* Metoda <code>priselZakaznik()</code> bude delegovat volání na <code>kalkulacka.pricti(1)</code>.
 +
* Dědičnost by zde nebyla vhodná, ostatní metody třídy <code>Kalkulacka</code> '''nemají''' být součástí rozhraní třídy <code>CitacPrichodu</code>.
 +
</div>
 +
 
=== Operátory <code>this</code> a <code>super</code> ===
 
=== Operátory <code>this</code> a <code>super</code> ===
 
* <code>this</code>... odkaz na objekt, jehož metodu právě provádíme.
 
* <code>this</code>... odkaz na objekt, jehož metodu právě provádíme.
 
* <code>super</code>... odkaz na rodičovskou třídu (používáme typicky v konstruktoru nebo k volání překrytých metod).
 
* <code>super</code>... odkaz na rodičovskou třídu (používáme typicky v konstruktoru nebo k volání překrytých metod).
  
== Příklady použití rysů OOP v knihovnách Javy ==
+
<!--
 +
== Příklady použití rysů OOP v Javě ==
 
;Polymorfismus
 
;Polymorfismus
 
* <code>Component.paint()</code>
 
* <code>Component.paint()</code>
 
** každá komponenta reaguje jinak
 
** každá komponenta reaguje jinak
 
** některé komponenty delegují volání na další vnořené komponenty.
 
** některé komponenty delegují volání na další vnořené komponenty.
;Skládání
+
-->
*Čítač příchodů
+
** Představme si, že máme již vytvořenou třídu <code>Kalkulacka</code> s metodou <code>pricti(cislo)</code>
+
** Můžeme využít instanci třídy <code>Kalkulacka</code> jako atribut.
+
** Metoda <code>priselZakaznik()</code> bude delegovat volání na <code>kalkulacka.pricti(1)</code>.
+
** Dědičnost by zde nebyla vhodná, ostatní metody třídy <code>Kalkulacka</code> '''nemají''' být součástí rozhraní třídy <code>CitacPrichodu</code>.
+
  
 
== Zdroje ==
 
== Zdroje ==
 
* [http://cs.wikipedia.org/wiki/Objektově_orientované_programování Wikipedia.org > Objektově orientované programování]
 
* [http://cs.wikipedia.org/wiki/Objektově_orientované_programování Wikipedia.org > Objektově orientované programování]
 
* [http://jaksenaucitprogramovat.py.cz/cztutclass.html JakseNaucitProgramovat.py.cz > Cztutclass]
 
* [http://jaksenaucitprogramovat.py.cz/cztutclass.html JakseNaucitProgramovat.py.cz > Cztutclass]

Verze z 17. 2. 2014, 10:47


Obsah

Co je to OOP?

Základní paradigma OOP

Cíle

Představte si, že někdo vytvořil knihovnu, která řeší obecnou úlohu (třeba ArrayList v Javě, fungující jako úložiště objektů).

Když tuto knihovnu chcete použít, potřebujete vědět:

  • hodnotu kterých proměnných můžete měnit,
  • které metody/funkce/procedury smíte volat.

To samozřejmě lze napsat do dokumentace. OOP je však vedeno snahou, aby zodpovězení těchto otázek bylo přirozenou součástí kódu.

Model systému pohledem OOP (konstrukty OOP)

Objekt
Zpráva
Rozhraní objektu/třídy
Třída
Instance
Atributy
Stav objektu

Rysy OOP

Abstrakce (abstraction)
Zapouzdření (encapsulation)
Polymorfismus (polymorphism)
Skládání (agregation)
Delegování (delegation)
Dědičnost (inheritance)

Použití konstruktů OOP v programovacích jazycích

Syntaxe Javy viz Java: Zápis tříd.

Objekty, třídy

Vytváření objektů (instancí třídy)
Konstruktor

Zprávy → metody

Metoda má
Přetěžování metod (overloading)
Překrývání metod (overlaying)
Atomizace metod

Atributy → proměnné

Instanční proměnné
Například třída UcebniSkupina může mít atribut počet žáků (kteří do dané skupiny chodí). Odpovídající proměnná musí být instanční, protože každá učební skupina může mít jiný počet žáků. (Je to vlastnost konkrétní skupiny.)
Třídní proměnné
Například je-li maximální počet žáků v učební skupině dán zákonem (pro všechny učební skupiny stejný), pak tento atribut budeme realizovat třídní proměnnou třídy UcebniSkupina.

Přístupnost metod a proměnných

Dědičnost

Zastupitelnost tříd

Abstraktní třída

Rozhraní (interface)

Nepleťte s pojmem „rozhraní třídy“ ve smyslu souhrnu všech metod!
Pokud implementujeme interface, pak „slibujeme“, že součástí rozhraní třídy jsou minimálně metody, zahrnuté v interface.

Dědičnost × Skládání — Čítač příchodů
  • Představme si, že máme již vytvořenou třídu Kalkulacka s metodou pricti(cislo).
  • Máme vytvořit třídu CitacPrichodu, která při každém průchodu dveřmi přičte do pomocné proměnné jedničku.
  • Napadne nás, že bychom mohli použít už fungující kód třídy Kalkulacka
  • Použijeme tedy instanci třídy Kalkulacka jako atribut třídy CitacPrichodu.
  • Metoda priselZakaznik() bude delegovat volání na kalkulacka.pricti(1).
  • Dědičnost by zde nebyla vhodná, ostatní metody třídy Kalkulacka nemají být součástí rozhraní třídy CitacPrichodu.

Operátory this a super


Zdroje

Osobní nástroje
Jmenné prostory
Varianty
Akce
Výuka
Navigace
Nástroje