PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

47
PB161 PB161 – Zapouzdření, dědičnost, 27.9.2010 1 /51 Principy OOP, zapouzdření, dědičnost

Transcript of PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

Page 1: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010 1

/51

Principy OOP, zapouzdření, dědičnost

Page 2: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010 2

/51

Co nás dnes čeká…

Více o objektovém návrhuKonstruktor, referencePrincip a implementace zapouzdřeníDědičnost

Page 3: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010 3

/51

Připomenutí

Třída je podklad pro tvorbu objektůObjekt je paměťová instance třídyTřída obsahuje datové atributy a metody pro práci

s nimi

Objekt mouse1

Třída CMouseAtribut m_size

Metoda feed

Page 4: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010 4

/51

Připomenutí (2)

Objekt má svůj stav (v datových atributech)● s atributy lze typicky pracovat jen přes metody

(zapouzdření)

Lze volat metody objektu● manipulují s atributy objektu

● const metody lze volat i nad konstantním objektem

Page 5: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010 5

/51

Deklarace vs. definice

Deklarace zavádí nové jméno entity do programu● typicky v hlavičkovém souboru (*.h)

Definice poskytuje unikátní popis (implementaci) entity ● funkce, typ, třída, instance...● typicky ve zdrojovém souboru (*.cpp)

Jen jedna definice (implementace), možno více deklaracíDeklarace může být zároveň definice

● např. deklarace metody přímo doplněná jejím tělem

Page 6: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010 6

/51

Ukázka třídy rozdělené do H a CPP

cmouse.h cmouse.cpp

deklarace

deklarace

deklarace i definice

definice

definice

import deklarací

Page 7: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010 7

/51

Výpis na standardní výstup

Z C znáte printf(“Dnes je %d. zari”, den);V C++ na výstup zapíšete takto:

Práci se standardním výstupem budeme dělat detailněji v 4. přednášce

Standardní výstup je objekt cout

Operátor << davá na cout řetězcovou reprezentaci argumentu těsně za nímAnalogie

<stdio.h>

Page 8: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010 8

/51

Konstruktor - motivace

Motivace: Naše třída má několik atributů● Jaká bude jejich hodnota při vytvoření objektu?● většinou neinicializovaná => nepříjemné

Možným řešením je speciální metoda „clean()“● ale „zbytečné“ volání hned po vytvoření objektu

C++ nabízí elegantní řešení - konstruktor

Page 9: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010 9

/51

Konstruktor

Metoda, která je automaticky volána při vytváření objektuZajistí, že objekt bude od začátku v konzistentním stavu

● můžeme inicializovat atributy na defaultní hodnotu● můžeme je nastavit na speciální hodnoty● můžeme otevřít spojení na server…

Konstruktor může mít argumenty a může být přetížen● inicializace uživatelem zadanými hodnotami● více konstruktorů s různými argumenty (přetížení)

Page 10: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

10/51

Konstruktory - syntaxe

jméno metody jako třída

Implementace konstruktorů

Deklarace konstruktorůs 0, 1 a 2 parametry

bez návratové hodnoty

Page 11: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

11/51

Defaultní konstruktor

Co když není definován žádný konstruktor?● automaticky existuje defaultní konstruktor● nemá žádné argumenty● CClass object;

Definováním uživatelského konstruktoru se odstraní defaultní konstruktor bez argumentů● pokud chceme konstruktor bez parametrů, musíme ho

definovat

Page 12: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

12/51

Kostruktory - ukázka

constructorDemo.cpppoužití konstruktoruneinicializovaná proměnnádefaultní konstruktorkonstruktor s argumentypřetížení konstruktoru

Page 13: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

13/51

Reference na proměnnou

Alternativní jméno pro objekt/proměnou (~alias)● často použito pro předávání referencí● není ukazatel na objekt, ale má podobné použití● změna proměnné obsahující referenci na objekt změní tento

objekt

Typově bezpečnější analogie k ukazateli na objekt● jde o referenci s konkrétním typem, ne např. void*● v C lze samozřejmě také ukazatel s konkrétním typem● nelze ale ukazatel na strukturu houseMouse nebo fieldMouse

Page 14: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

14/51

Předávání argumentů referencí

Alternativa k předávání argumentů funkce ukazatelem● volání odkazem: void foo(int* pX) { *pX = 10; } ● volání referencí: void foo(int& x) { x = 10; }

Zavolání funkce vypadá jako volání hodnotou● při předávání referencí není vytvářena kopie objektu

● změna argumentu uvnitř funkce se ale projeví i mimo funkci

Page 15: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

15/51

Konstantní reference

Konstantní reference (const typ&)● umožňuje specifikovat záměr programátoru o

nakládání s objektem (referencí, ale nebude měněn)

Kontrolováno během překladu● konstatní reference na nekonstantní objekt - chyba

● změna nekonstantního objektu přes konstantní referenci - chyba

Page 16: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

16/51

Reference - ukázka

referenceDemo.cppvíce referencí na jedinou proměnnounutnost inicializace referencepředání argumentu referencízměna hodnoty mimo funkcikonstantní reference

Page 17: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

17/51

ZapouzdřeníDědičnostAbstrakcePolymorfismus

Page 18: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

18/51

Zapouzdření

Zapouzdření je styl programování● snaží se minimalizovat viditelnost proměnných/funkcí● aby nedocházelo k nezáměrným/nevhodným změnám● uživatel používá jen podmnožinu vybraných funkcí

Kombinace několika vlastností ● abstrakce dat/metod (abstraction)

● skrytí dat/metod (hidding)● zapouzdření dat (data encapsulation)

Page 19: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

19/51

Abstrakce dat/metod (abstraction)

Datová abstrakce● data mohou být použita, aniž by uživatel znal způsob

jejich reprezentace v paměti

● např. databáze jako soubor na disku nebo vzdáleném serveru

Funkční abstrakce● metoda může být použita, aniž by uživatel znal způsob

její implementace

● např. metoda pro vykreslení objektu

Page 20: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

20/51

Skrytí dat/metod (hidding)

Pro okolí jsou vnitřní data třídy skryta ● atribut třídy může být pro okolí nepřístupný

Nemusejí být ani metody pro přímé získání a nastavení hodnoty atributu● atribut se může projevovat jen vlivem na chování

ostatních funkcí

Pro okolí jsou interní metody skryty● nejsou součástí veřejného rozhraní třídy

Page 21: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

21/51

Zapouzdření dat (encapsulation)

S daty lze pracovat jen prostřednictvím obalujících funkcí● nelze přímo číst/nastavit hodnotu datového atributu● např. dostupná pouze CMouse::feed(), ne CMouse::setSize()

Obalující metody mohou kontrolovat● validitu argumentů, konzistentnost vnitřního stavu před změnou…● metoda může nadstavovat více vnitřních atributů zároveň

Uživatel třídy není omezován detaily vnitřní logiky

Page 22: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

22/51

Výhody zapouzdření

Implicitní tlak na dělitelnost a nezávislost kóduImplementace třídy se může vyvíjet bez nutnosti

změny okolního kódu ● rozhraní zůstává neměnné

Vnitřnosti třídy jsou lépe chráněny vůči chybám ● programátor je omezen a kontrolován překladačem

Příprava pro další OOP vlastnosti

Page 23: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

23/51

Zapouzdření v C++

C++ poskytuje nástroje pro zapouzdření dat ● ale umožňuje i porušit (tj. přímý přístup)

Realizováno prostřednictvím přístupových práv● k atributům

● k metodám

Základní přístupová práva● public – všichnu mohou číst/modifikovat/používat● private – nikdo kromě vlastní třídy nemůže

číst/používat

● protected, friend – specializovanější (později)

Page 24: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

24/51

Syntaxe přístupových práv

Struktura

Třída

změna z public na private

změna z private na public

Page 25: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

25/51

Přístupová práva

Právo platí, dokud není nastaveno jinéstruct v C++ má všechny položky defaultně public

● z důvodu zpětné kompatibility s C● lze přenastavit na private

class v C++ má všechny položky defaultně private● ponechte pro atributy private● je nutné explicitně nastavit public pro veřejné metody

Page 26: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

26/51

Přístupová práva - public

K položce s právem public má přístup kdokoli● atribut může být čten a měněn kýmkoli● metoda může být volána „zvenčí“

Jako public typicky neoznačujeme atributy● podporujeme zapouzdření

Jako public označujeme metody, které jsou součástí rozhraní● deklarace existujících public metod by se neměly měnit

● někdo je nejspíš používá● implementaci měnit můžeme (tělo je skryto)

Page 27: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

27/51

Přístupová práva - private

K položce s právem private má přístup pouze sama třída● atribut nebo metoda nemůže být použit/volána „zvenčí“● výjimkou je objekt/metoda s právem friend (viz. později)● pokus o použití metody definované jako private vyvolá chybu už

během překladu

Jako private označujeme typicky všechny atributy● podporujeme zapouzdření

Jako private označujeme metody, které nejsou součástí rozhraní● nechceme, aby na nich někdo závisel

Page 28: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

28/51

Přístupová práva - ukázka

accessRightsDemo.cppdeklarace veřejných a privátních atributůrozdíly class vs. structchyby překladače

● přístup k privátnímu atributu● přístup k privátní metodě

Page 29: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

29/51

ZapouzdřeníDědičnostAbstrakce Polymorfismus

Page 30: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

30/51

Dědičnost v OOP

Duplicita v kódu je nepříjemná● snižuje přehlednost● zvyšuje náročnost úprav (nutno na více místech)● zvyšuje riziko chyby (někde zapomeneme upravit)

Dědičnost je nástroj pro omezení duplicity v kóduZlepšuje možnost znovuvyužití existujícího kódu

Page 31: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

31/51

“Dědičnost” v C

V C se duplicita kódu odstraňuje: ● vytvořením nové funkce● a vložením funkčního volání na původní místa

Znovuvyužití kódu se dosahuje ● dobrým návrhem funkčního rozhraní

● umístěním do samostatných hlavičkových souborů

Page 32: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

32/51

Dědičnost v C++

V C++ existuje systematičtější podpora● lze odstranit duplicitu i pro proměnné● navíc podporuje silnou typovou kontrolu

Mechanismus umožňující vytvořit další třídu (potomek) s využitím předlohové třídy (předek)● potomek zdědí možnosti předka (atributy a metody)

● může je rozšiřovat a předefinovat (překrývat)

Page 33: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

33/51

Dědičnost - postup

1. Máme dvě (nebo víc) tříd se společným chováním

2. Identifikujeme společnou logiku (metody)

3. Identifikujeme společná data (atributy)

4. Vytvoříme novou třídu (předka)● obsahující společné atributy a logiku

1. Odstraníme přesunuté atributy&metody z původních tříd

2. Původní třídy nastavíme jako potomky nového předka

Page 34: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

34/51

Dědičnost - příklad

V laboratoři máme domácí a polní myš. Rozdíl mezi druhy je jen v počáteční velikosti a rychlosti přibírání po požití potravy.

Nové třídy CHouseMouse a CFieldMouseSpolečné vlastnosti přesunuty do CMouseBaseCHouseMouse a CFieldMouse potomci

CMouseBase

Page 35: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

35/51

Dědičnost - syntaxe

Předek

Potomek

Hlavičkový soubor předka

Modifikátor definující způsob dědění metod

a atributů

Page 36: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

36/51

Přístupová práva - protected

K položce s právem protected má přístup pouze potomek● atribut může být čten a měněn potomkem ● metoda nemůže být volána „zvenčí“

Jako protected typicky označujeme metody● které nemají být dostupné všem, ale potomkům ano● často jde o virtuální přetěžované metody (později)● méně často atributy – raději protected „setter“ metodu

Page 37: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

37/51

Typová hierarchie

Dědičnost vytváří hierarchii objektů● od nejobecnějšího k nejspecifičtějším

Na místo předka může být umístěn potomek ● proměnná s typem předka může obsahovat potomka

● potomek může být argumentem funkce s typem předka

● zároveň zachována typová bezpečnost

Při dědění lze omezit viditelnost položek předka● specifikace práv při dědění

Page 38: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

38/51

Specifikátory přístupových práv dědění

public (class B : public A {}; )● zděděné položky dědí přístupová práva od předka● práva zůstanou jako předtím

private (class B : private A {}; )● zděděné položky budou private, odvozená třída však

bude mít přístup ke položkám, pokud byly v předkovi public nebo protected

● nebude přístup k položkám private u předka

● v potomcích potomka už nebude přístup

Page 39: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

39/51

Specifikátory dědění přístupových práv (2)

protected (class B : protected A {}; )● položky private a protected zůstanou stejné, z public se

stane protected

pokud neuvedeme (class B : A {}; )● class jako private, u struct a union jako public

virtual (class B : virtual A {}; )● lze kombinovat s jedním z předchozích, přikazuje

pozdní vazbu – (viz později)

Page 40: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

40/51

Práva při dědění - ukázka

inheritanceRightsDemo.cpppřístup k private metoděpřístup při dědění public/private/protectedzměna práv pro přístup při opakovaném děděnízpůsob znepřístupnění původně public metody

Page 41: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

41/51

Jak „dědit“ z více existujících tříd?

Nová třída má mít vlastnosti více objektů● v Jave se řeší pomocí interfaces

V C++ lze řešit ● pomocí násobné dědičnosti (třída má více předků)

● pomocí kompozice objektu (třída má více podčástí)

Page 42: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

42/51

Syntaxe násobné dědičnosti

Syntakticky správně, je ale vhodné?

Předek 1

Předek 2

Dědíme z obou předků

Page 43: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

43/51

Dědičnost vs. kompozice

Dědičnost je „Is-A“ vztah● potomek má všechny vnější vlastnosti předka A● potomka můžeme přetypovat na předka

Kompozice je „Has-A“ vztah● třída může mít jako atribut další třídu A

● hodnotou, referencí, ukazatelem

● třída obsahuje vlastnosti A a další● třída může mít víc tříd jako své atributy

Page 44: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

44/51

Dědičnost vs. kompozice - ukázka

inheritanceCompositionDemo.cppnásobná dědičnostkompozicevyužití inicializační sekce konstruktorupřetypování na předka

Page 45: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

45/51

Dědičnost – vhodnost použití

Dle použití lze volit mezi dědičností a kompozicíObecně preference kompozice před dědičností

● násobná dědičnost může být nepřirozená● kompozice může být kódově rozsáhlejší

Možná i kombinace● objekt obsahuje kompozicí třídy jako atributy● jednotlivé atributy mohou mít hierarchii dědičnosti

Page 46: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

46/51

Shrnutí

Konstruktor je metoda pro inicializaci objektuReference je zástupné jméno (alias) na objekt

● při předávání referencí můžeme objekt trvale měnit

Zapouzdření skrývá vnitřní data a logiku● umožňuje abstrahovat uživatele od aktuální

implementace

Dědičnost umožňuje využít kód předka v potomkovi● potomek může vystupovat jako datový typ předka

Násobná dědičnost vs. kompozice

Page 47: PB161 - Týden 2 - Principy OOP, zapouzdření, dědičnost

PB161PB161 – Zapouzdření, dědičnost, 27.9.2010

47/51