1. Programování proti rozhraní

Podobné dokumenty
Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

typová konverze typová inference

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

3. Je defenzivní programování technikou skrývání implementace? Vyberte jednu z nabízených možností: Pravda Nepravda

Úvod do programovacích jazyků (Java)

1. Dědičnost a polymorfismus

Programování v Javě I. Únor 2009

Programování v Javě I. Leden 2008

Dalším příkladem může být například výstup dat na různá zařízení, souborů, grafických rozhraní, sítě atd.

8 Třídy, objekty, metody, předávání argumentů metod

Abstraktní datové typy: zásobník

Výčtový typ strana 67

Seminář Java II p.1/43

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

KTE / ZPE Informační technologie

Generické programování

Algoritmizace a programování

Úvod do programovacích jazyků (Java)

IB111 Programování a algoritmizace. Objektově orientované programování (OOP)

PREPROCESOR POKRAČOVÁNÍ

PB161 Programování v jazyce C++ Přednáška 7

PB161 Programování v jazyce C++ Přednáška 7

10 Balíčky, grafické znázornění tříd, základy zapozdření

Počítačové laboratoře bez tajemství aneb naučme se učit algoritmizaci a programování s využitím robotů CZ.1.07/1.3.12/

7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd

Tento studijní blok má za cíl pokračovat v základních prvcích jazyka Java. Konkrétně bude věnována pozornost rozhraním a výjimkám.

Úvod do programování - Java. Cvičení č.4

TŘÍDY POKRAČOVÁNÍ. Události pokračování. Příklad. public delegate void ZmenaSouradnicEventHandler (object sender, EventArgs e);

TÉMATICKÝ OKRUH Softwarové inženýrství

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

IRAE 07/08 Přednáška č. 7. Začátek (head)

9. Polymorfismus a rozhraní

Třídy, polymorfismus. A0B36PR2-Programování 2 Fakulta elektrotechnická České vysoké učení technické

Programování II. Návrh programu I 2018/19

Algoritmizace a programování

Dynamicky vázané metody. Pozdní vazba, virtuální metody

Programové konvence, dokumentace a ladění. Programování II 2. přednáška Alena Buchalcevová

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

PŘETĚŽOVÁNÍ OPERÁTORŮ

Objektově orientované programování v jazyce Python

1. Téma 03 - Rozhodování

RMI Remote Method Invocation

Z. Kotala, P. Toman: Java ( Obsah )

Programovací jazyk Java

Programování II. Dědičnost změna chování 2018/19

Třídy. Instance. Pokud tento program spustíme, vypíše následující. car1 má barvu Red. car2 má barvu Red. car1 má barvu Blue.

Dědění, polymorfismus

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Bridge. Známý jako. Účel. Použitelnost. Handle/Body

7 Formátovaný výstup, třídy, objekty, pole, chyby v programech

Abstraktní třída a rozhraní

Algoritmizace. Cíle předmětu

7. Datové typy v Javě

Objektově orientované programování

11 Diagram tříd, asociace, dědičnost, abstraktní třídy

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Obsah přednášky 9. Skrývání informací. Skrývání informací. Zapouzdření. Skrývání informací. Základy programování (IZAPR, IZKPR) Přednáška 9

Programování v C++ 2, 4. cvičení

Objektově orientované programování v jazyce Python

Statické proměnné a metody. Tomáš Pitner, upravil Marek Šabo

Objektově orientované programování. Úvod

PB161 Programování v jazyce C++ Přednáška 9

Programování v C++ 3, 3. cvičení

11. Přehled prog. jazyků

IRAE 07/08 Přednáška č. 2. atr1 atr2. atr1 atr2 -33

Mnohotvarost (polymorfizmus)

Základy objektové orientace I. Únor 2010

Jazyk C++ 1. Blok 3 Objektové typy jazyka C++ Třída. Studijní cíl. Doba nutná k nastudování. Průvodce studiem

Java Cvičení 01. CHARLES UNIVERSITY IN PRAGUE faculty of mathematics and physics

NMIN201 Objektově orientované programování 1 / :36:09

Dědičnost (inheritance)

29. Výjimky, jejich vznik, vyhození, odchyt a zpracování. (A7B36PVJ)

Datové struktury. alg12 1

Java Výjimky Java, zimní semestr

Vyřešené teoretické otázky do OOP ( )

Pokročilé programování v jazyce C pro chemiky (C3220) Pokročilá témata jazyka C++

Teoretické minimum z PJV

IRAE 07/08 Přednáška č. 1

Seznamy a iterátory. Kolekce obecně. Rozhraní kolekce. Procházení kolekcí

Quo vadis programování? Automatizace vyhodnocování studentských úloh

Seminář Java IV p.1/38

Jazyk C++ II. Šablony a implementace

4. ZÁKLADNÍ POJMY Z OBJEKTOVĚ ORIENTOVANÉHO PROGRAMOVÁNÍ

Při studiu tohoto bloku se předpokládá, že student je zvládá základy programování v jazyce Java s využitím vývojového prostředí NetBeans.

NPRG031 Programování II 1 / :25:46

Java - výjimky. private void vstup() throws IOException {... }

24. listopadu 2013, Brno Připravil: David Procházka

Jazyk C# (seminář 6)

10. března 2015, Brno Připravil: David Procházka. Programovací jazyk C++

Jazyk C++ I. Šablony 2

Konstruktory a destruktory

Připravil: David Procházka. Programovací jazyk C++

Polymorfismus. Časová náročnost lekce: 3 hodiny Datum ukončení a splnění lekce: 30.března

3. Třídy. Základní pojmy objektového programování. Třídy

Jazyk C++ I. Šablony

Pokročilé programování v jazyce C pro chemiky (C3220) Operátory new a delete, virtuální metody

Class loader. každá třída (java.lang.class) obsahuje referenci na svůj class loader. Implementace class loaderu

Sémantika Tabulka symbolů Intermediální kód Typová kontrola, přetypování Statická a dynamická sémantika. Sémantická analýza.

17. Projekt Trojúhelníky

Transkript:

1. Programování proti rozhraní Cíl látky Cílem tohoto bloku je seznámení se s jednou z nejdůležitější programátorskou technikou v objektově orientovaném programování. Tou technikou je využívaní rozhraní jako datového typu při deklarování proměnných. 1.1. Úvod Pro správné pochopení zásady, co je to programování proti rozhraní, je nutné nejdříve definovat co je to rozhraní. Definic je celá řada. Jedna z nich rozhraním rozumí souhrn informací, které o sobě daná entita (atribut, metoda, třída) zveřejňuje. Rozhraní tedy obsahuje informace, které mohou kooperující programy využívat, resp. které musí respektovat. Informace deklarované v rozhraní lze rozdělit do dvou kategorií: 1. ty, které, tvoří signaturu 2. to co obsahuje kontrakt 1.1.1. Signatura Signaturu tvoří souhrn informací ve zdrojových kódech, které zpracovává překladač. Nerespektování pravidel signatury se projeví jako syntaktická chyba, kterou je nutné opravit. Podle dané struktury objektově orientovaného programovacího jazyka může být několik úrovní signatury. Typicky jsou známy tyto úrovně: Signatura dat název proměnné nebo konstanty a jejich typ Signatura metod název metody návratový typ typy jednotlivých parametrů Signatura tříd a datových typů název typu případně název předka seznam implementovaných rozhraní signatury všech členů tj. atributů metod signatury zanořených tříd Do signatury dat se zahrnují především deklarace konstant a proměnných, kdy musí být definováno: Do signatury metod patří: Do signatury tříd patří: 1

Takto přísně definovaná signatura dat platí pro jazyky se statickou typovou kontrolou jako jsou například C++, JAVA, C# tj. pro jazyky, které provádějí typovou kontrolu v době překladu. Některé programovací jazyky, jako jsou Lisp, PHP, Python, Ruby nebo Smalltalk, používají tzv. dynamickou typovou kontrolou, která se provádí za běhu programu. U signatury metod stojí za pozornost si uvědomit, že součástí signatury nejsou názvy parametrů. Sice součástí signatury je i návratový typ, ale nelze v jedné třídě deklarovat dvě metody se stejnou signaturou tj. stejným názvem, počtem, typem parametrů a odlišit je pouze návratovým typem. U signatury tříd a datových typů je nutné si všimnout, že do signatury patří všechny členy třídy, včetně signatur vnořených a vnitřních tříd. Zase zde platí, že vše musí být syntaktický správně. 1.1.2. Kontrakt Kontraktem se specifikují informace o rozhraní, které překladač nedokáže zkontrolovat, ale jsou důležité pro pochopení užití daného rozhraní. Do kontraktu patří například: omezení na rozsah vstupních parametrů metod některé dodatečné povinné vlastnosti výsledků metod informace o tom, že při implementaci jedné metody je využitá jiná metoda upozornění na speciální algoritmus, který by mohl využít případný potomek Protože kontrakt nelze kontrolovat překladačem, měl by každý kdo chce dané rozhraní použít se s kontraktem předem seznámit, aby se vyhnul při jeho porušení problémům. Sice kontrakt nelze kontrolovat překladačem to však neznamená, že by nešel vůbec zkontrolovat. Kontroluje se však až za běhu programu vložením vhodných kontrolních příkazů, které ověřují platnost vstupních a výstupních podmínek. Java pro tento účel zavedla ve verzi 1.4 klíčové slovo assert. Výpis 1.1. Příklad na použití příkazu assert class TestAssert { static double prevracena_hodnota(double x) { assert x!= 0.0 : "Argument nesmi byt nulovy"; return 1.0 / x; public static void main(string args[]) { System.out.println(prevracena_hodnota(1)); System.out.println(prevracena_hodnota(0)); Příklad použití příkazu assert jako kontroly nepřípustné hodnoty v parametru. V případě, že se objeví nulová hodnota v parametru x, vystaví 2

se výjimka AssertionError. Text za dvojtečkou se vypíše současně s výjimkou. Exception in thread "main" java.lang.assertionerror: Argument nesmi byt nulovy at javaapplication2.testassert.prevracena_hodnota(testassert.java:6) at javaapplication2.testassert.main(testassert.java:11) Vyvolání metody s nepovolenou hodnotou argumentu. Výhoda používaní příkazu assert je v tom, že jeho vykonávání se dá vypínat. To umožňuje, po odladění aplikace, vykonávání kontrol vypnout a tím zrychlit její běh. Příklad jak spustit nebo vynech kontrolu pomocí příkazů assert javac -source 1.4 TestAssert.java java TestAssert java -ea TestAssert Příkaz přeložení programu TestAssert ve verzi Javy 1.4 Spuštění přeloženého programu bez zapnutých kontrol Spuštění programu se zapnutými kontrolami příkazů assert. Kontrole vstupních a výstupních podmínek přímo v kódu se někdy říká, že se programuje defenzivně. Defenzivní programování, vychází z předpokladu, že co je mimo vlastní kód, může tento kód ohrozit. To ohrožení může být neúmyslné, ale bohužel někdy s cílem způsobit škodu nebo získat nějakou neoprávněnou výhodu. Defenzívní programování na Wikipedii [http://cs.wikipedia.org/wiki/defenzivn %C3%AD_programov%C3%A1n%C3%AD] 1.1.3. Jak dodržovat zásadu Základní myšlenkou zásady je omezit deklarovat proměnné pomocí instančních, konrétních tříd. Lepší je nahradit tyto deklarace pomocí nějakého datového typů, která není vázana na nějakou konkrétní implementaci. Takovým typem je právě interface nebo abstraktní třída. 1.1.4. Návrh vlastního rozhraní Při návrhu rozhraní se má myslet především na budoucího uživatele a ne na to, jak bude toto rozhraní implementováno. Mezi těmeto dšma přístupy je podstatný rozdíl. Rozhraní se má navrhovat tak, aby se budoucímu uživateli s ním dobře pracovalo a tedy nesmí se při jeho návrhu myslet na to, aby se dobře implementovalo programátorovi. Zde je dobré si uvědomit, že se zde se nejedná o uživatelské rozhraní celkové aplikace, ale o aplikační programátorské rozhraní, které je všeobecně známo pod zkratkou API (Application Programming Interface). API používají programátoři, když začleňují cízí části programu do svého programu. Rozhraní specifikované pomocí inteface umožňuje mnohem lépe skrýt implementaci vyvíjeného programu a tím umožnit jeho snadnější vylepšování a upravování. 3

1.1.5. Ukázka rozdílu Na následujícíh dvou diagramech 1.1 a 1.2 je ukázán rozdíl mezi programování proměnných proti instačním konkrétním třídám a proti rozhraní. Obrázek 1.1. Programování proměnných proti instanci Obrázek 1.2. Programování proměnných proti rozhraní Ukázka programování proti instančním třídám public class Ucet { private int cislo; private long zustatek; public Ucet(int cislo) { this.cislo = cislo; public int dejcislo() { Výpis 1.2. Instanční třída Ucet 4

return cislo; public long dejzustatek() { return zustatek; public void vlozcastku(long castka) { assert 0 < castka; zustatek += castka; Výpis 1.3. Třída Banka s instančními proměnnými public class Banka { private Ucet[] ucty; private int pocet; public Banka() { ucty = new Ucet[100]; pocet = 0; public long dejzustatek(int cislo) { Ucet u; u = najdiucet(cislo); if (u!= null) { return u.dejzustatek(); return 0; public void pridejucet(ucet ucet) { if (pocet < ucty.length) { ucty[pocet++] = ucet; public void vloznaucet(long castka, int cislo) { Ucet u; u = najdiucet(cislo); if (u!= null) { u.vlozcastku(castka); private Ucet najdiucet(int cislo) { Ucet u = null; for (int i = 0; i < pocet; i++) { if (ucty[i].dejcislo() == cislo) { u = ucty[i]; return u; 5

Výpis 1.4. Rozhraní IUcet public interface IUcet { public int dejcislo(); public long dejurok(); public long dejzustatek(); public void vlozcastku(long castka); Pro tvorbu jména rozhraní je dobré si zavést konvenci. V tomto případě je před významové jméno Ucet vložen prefix I. To výrazně zvyšuje čitelnost zdrojových kódů, kdy je jednoznačně řečeno, že proměnná je datového typy, že není vázaná na žádnou konrétní třídu. Výpis 1.5. Instanční třída BeznyUcet public class BeznyUcet implements IUcet { private int cislo; private long zustatek; public BeznyUcet(int cislo) { this.cislo = cislo; public int dejcislo() { return cislo; public long dejurok() { return 0; public long dejzustatek() { return zustatek; public void vlozcastku(long castka) { assert 0 < castka; zustatek += castka; Jestliže se chce zajistit, aby konkrétní třída měla předepsané rozhraní, musí se to překladači říct uvedením jména rozhraní za klíčové slovo implements. Překladač potom zajistí, zda všechny signatury metod jsou v dané konkrétní třídě implementovány. Metody, které vnutí třídě rozhraní a které nemají v dané třídě smysl, se musí též implementovat. Většinou se voli nějaká neutrální reakce nebo se vyvolá výjimka. Výpis 1.6. Instanční třída SporiciUcet public class SporiciUcet implements IUcet { 6

private int cislo; private float urok; private long zustatek; public SporiciUcet(int cislo) { this.cislo = cislo; public int dejcislo() { return cislo; public long dejurok() { return (long) (zustatek * urok); public long dejzustatek() { return zustatek; public void vlozcastku(long castka) { if (0 < castka) { zustatek += castka; Metoda dejurok() u spořícího učtu již smysl má, takže vrací výpočet úroku ze zůstatku. Tyto metody jsou implementovány stejné jako metody se stejnou signaturou ve třídě BeznyUcet. To znamená, máme duplicitní kód. Takže tyto dvě třídy jsou kandidáti na zevšeobecnění. Výpis 1.7. Využití rozhraní jako datového typu ve třídě Banka, public class Banka { private IUcet[] ucty; private int pocet; public Banka() { ucty = new IUcet[100]; pocet = 0; public long dejzustatek(int cislo) { IUcet u; u = najdiucet(cislo); if (u!= null) { return u.dejzustatek(); return 0; public void pridejbeznyucet(iucet ucet) { 7

if (pocet < ucty.length) { ucty[pocet++] = ucet; public void vloznaucet(long castka, int cislo) { IUcet u; u = najdiucet(cislo); if (u!= null) { u.vlozcastku(castka); private IUcet najdiucet(int cislo) { IUcet u = null; for (int i = 0; i < pocet; i++) { if (ucty[i].dejcislo() == cislo) { u = ucty[i]; return u; Prvky pole účtů je typu IUcet. To je možné v Java, protože pole je polem referencí. Při vytvoření pole se musí též použít datový typ IUcet, protože to pale ja tak deklarováno. Že to je možné, je zase dáno tím, že pole je polem referencí a ne polem objektů. Datový typ rozhraní IUcet lze zase použít i jako typ parametru metody. To samé, jako v přechozím bodě, platí i pro typ navratové hodnoty při volaní metody. Důležitá pasáž Třída Banka, z přechozího příkladu, je zcela nezávislá na tom, z jakou konkrétní instanční třídou bude pracovat. Tedy jinak řečeno, tato třída je zcela nezávislá na budoucích implementacích. 1.1.6. Jak na změnu rozhraní Jakmile se jednou zveřejní rozhraní, už by se nemělo měnit. Důvod je jednoduchý, protože se do potíží mohou dostat všichni ostatní programátoři, kteří toto rozhraní vyžívají ve svých kódech. Totiž by musel by přeprogramovat všechny své odladěné a otestované zdrojové kódy. Pokud je nezbytné rozhraní doplnit, je lépe definovat nové rozhraní nebo ho rozšířit pomocí dědičnosti. Po rozšíření nebo změně rozhraní se programátoři můžou rozhodnout, zda tyto rozšíření zapracují do svého kódu nebo ne. 8