Objektově orientované programování
V informatice je objektově orientované programování programovacím paradigmatem , které vám umožňuje definovat softwarové objekty , které se mohou vzájemně ovlivňovat prostřednictvím výměny zpráv . Obzvláště vhodná v kontextech, ve kterých lze definovat vztahy vzájemné závislosti mezi koncepty, které mají být modelovány (uzavření, použití, specializace), oblast, která více než ostatní dokáže využít výhod objektově orientovaného programování, je oblast grafických rozhraní .
Mezi další výhody objektově orientovaného programování patří:
- poskytuje přirozenou podporu softwarovému modelování objektů reálného světa nebo abstraktního modelu, který má být reprodukován;
- umožňuje snadnější správu a údržbu velkých projektů;
- organizace kódu ve formě tříd upřednostňuje modularitu a opětovné použití kódu .
Historie
Koncept třídy lze považovat za dědice abstraktního datového typu , konceptu, který se původně vyvíjel v rámci paradigmatu procedurálního programování , které poskytuje definici datových typů , s nimiž lze komunikovat pouze prostřednictvím dobře definovaného rozhraní
Syntaktické konstrukce, které umožňují definovat třídu v objektově orientovaných jazycích, lze považovat za strukturovanou podporu pro vytváření abstraktních dat.
První objektově orientovaný programovací jazyk byl Simula ( 1967 ), v 70. letech následoval Smalltalk a různá rozšíření Lisp . V osmdesátých letech byla vytvořena objektově orientovaná rozšíření jazyka C ( C++ , Objective-C a další) a dalších jazyků ( Object Pascal ). V devadesátých letech se to stalo dominantním paradigmatem, kdy většina programovacích jazyků byla buď nativně objektově orientovaná, nebo měla v tomto smyslu rozšíření. Jazyky, které podporují pouze objektově orientované programovací paradigma, jsou Smalltalk a Eiffel . Častěji se setkáváme s nevýhradní implementací objektově orientovaného programovacího paradigmatu jako v C++ , Java , Delphi , Python , C # , Visual Basic .NET , Perl , PHP (od verze 4).
Popis
Objektově orientované programování zahrnuje seskupení v omezené oblasti zdrojového kódu (nazývané třída ), deklaraci datových struktur a procedur , které s nimi pracují. Třídy tedy představují abstraktní modely, které jsou za běhu vyvolány k vytvoření instance nebo vytvoření softwarových objektů souvisejících s vyvolanou třídou. Ty jsou vybaveny atributy (daty) a metodami (procedurami), jak je definují / deklarují příslušné třídy.
Část programu, která využívá objekt, se nazývá klient .
Programovací jazyk je objektově orientovaný , když umožňuje implementovat tři mechanismy pomocí nativní syntaxe jazyka [1] :
- zapouzdření ;
- dědictví ;
- polymorfismus .
Zapouzdření spočívá v oddělení takzvaného rozhraní třídy od jeho odpovídající implementace, takže klienti objektu této třídy mohou používat první, ale ne druhý.
Dědičnost v podstatě umožňuje definovat třídy počínaje jinými již definovanými.
Polymorfismus vám umožňuje napsat klienta, který může používat objekty různých tříd, ale se stejným společným rozhraním ; za běhu tento klient spustí různé chování, aniž by předem znal konkrétní typ objektu, který je mu předán.
Třídy
Třídy definují datové typy a umožňují vytváření objektů podle charakteristik definovaných v samotné třídě. Díky vztahům dědičnosti je možné vytvářet nové třídy ze stávajících a rozšiřovat je o další funkce.
Třída se skládá z:
- atributy (analogické ke členům záznamu ), tj. proměnné a/nebo konstanty , které definují charakteristiky nebo vlastnosti objektů, které lze konkretizovat vyvoláním třídy; inicializované hodnoty atributů se získávají prostřednictvím takzvaného konstruktoru ;
- metody , tedy procedury , které pracují s atributy.
(Nepřesné) srovnání s matematikou je následující: můžeme si myslet, že třída definuje množinu intenzivním způsobem, to znamená, že spíše naznačuje její charakteristiky než vypisuje její prvky, a že objekty jsou prvky této množiny. V matematice je však počet prvků vnitřní charakteristikou množiny samotné a je definován, když je množina definována, zatímco v programování je možné instanci třídy vytvořit libovolný počet opakování (teoreticky od nuly do nekonečna; v praxi od nuly do vyčerpání paměti počítače ) a který závisí na provedení programu. Z tohoto důvodu je vhodnější považovat třídu za instantní abstraktní model.
Jinými slovy, třída je srovnatelná s projektem infrastruktury , kterou pak lze uvést do provozu/provozu nebo realizovat či nerealizovat s konkretizací svých objektů, všechny se stejnými charakteristikami nebo atributy (s různými hodnotami), na kterých metody nebo funkce budou fungovat.
Objekty
Objekt je instancí třídy. Má všechny atributy a metody definované třídou a funguje jako poskytovatel „zpráv“ (metody), které může spustitelný kód programu (procedury nebo jiné objekty) na požádání aktivovat.
Odeslání zprávy objektu znamená v žargonu vyvolání metody na daném objektu. Metoda přijímá jako parametr (často implicitní) objekt, na kterém byla vyvolána, na který lze odkazovat pomocí klíčového slova nebo specifické syntaxe, i když je předán jako implicitní parametr; například v C ++ , Java a C # je klíčové slovo použito this( $thisv PHP ), zatímco v Smalltalk , Objective-C , Python a Ruby se používá klíčové slovo self.
Z pohledu počítače je každý objekt identifikován určitou paměťovou oblastí , ve které jsou uloženy atributy a její hodnota určuje vnitřní stav objektu. Vytvořit instanci objektu znamená alokovat paměť a případně ji inicializovat podle specifikací definovaných třídou. Mnoho jazyků poskytuje podporu pro automatickou inicializaci objektu pomocí jedné nebo více speciálních metod, nazývaných konstruktory . Podobně lze konec životnosti objektu ošetřit metodou zvanou destruktor .
Spustitelný kód programu přistupuje k této oblasti paměti vždy a pouze způsobem definovaným třídou.
Podle principu známého jako skrývání informací musí být přístup k polím objektu povolen pouze prostřednictvím metod vyvolaných na stejném objektu. Hlavní výhodou je, že úplná kontrola nad vnitřním stavem je přiřazena omezené oblasti spustitelného kódu programu (třídě), protože externí kód není oprávněn jej upravovat. V tomto případě je možné zavést omezení na možné hodnoty, které atribut n-tice může nebo nemůže nabývat, a také na možné přechody mezi těmito stavy. Objekt lze tedy považovat za konečný automat .
Zapouzdření
Zapouzdření je vlastnost, pomocí které jsou data, která definují vnitřní stav objektu a metody, které definují jeho logiku, přístupné metodám samotného objektu, zatímco klienti je nevidí. Ke změně vnitřního stavu objektu je nutné vyvolat jeho veřejné metody, a to je hlavním účelem zapouzdření. Ve skutečnosti, pokud je správně spravován, umožňuje vidět objekt jako black-box , tedy „černou skříňku“, se kterou interakce probíhá pouze a pouze prostřednictvím metod definovaných rozhraním. Cílem je poskytnout uživatelům funkčnost skrytím podrobností souvisejících s jejich implementací. Příkladem může být "matematický" objekt, který mezi mnoha operacemi, které poskytuje, je ta, která násobí dvě čísla. Například moltiplica(2,3)vrátí 6. Nyní může být algoritmus násobení jedním z mnoha algoritmů, které existují, ale moltiplica()pro volajícího metody to nic nemění. Důležité je, že výsledek nemá chybu.
Dědičnost
Mechanismus dědičnosti se používá ve fázi strukturování/definice/plánování softwaru nebo v následných rozšířeních a umožňuje odvozovat nové třídy počínaje již definovanými třídami a vytvářet tak hierarchii tříd. Třída odvozená prostřednictvím dědičnosti ( podtřída nebo podřízená třída) si zachovává metody a atributy tříd, ze kterých je odvozena ( základní třídy , nadtřídy nebo rodičovské třídy); navíc může definovat své vlastní metody nebo atributy a předefinovat kód některých zděděných metod pomocí mechanismu zvaného overriding .
Když třída dědí pouze z jedné nadtřídy, nazývá se to jednoduchá dědičnost; naopak mluvíme o vícenásobném dědictví. Některé jazyky (kromě jiných Java, Smalltalk) poskytují jedinečnou podporu pro jedinou dědičnost. Jiné (C ++, Python) také umožňují vícenásobnou dědičnost.
Některé typy jazyků (Java, C #) umožňují dědění rozhraní a tříd.
Dědičnost lze použít jako mechanismus k dosažení rozšiřitelnosti a opětovného použití kódu a je zvláště výhodná, když se používá k definování podtypů , využívajících ve skutečnosti existující vztahy is-a , jejichž modelováním je struktura třídy. Kromě evidentního opětovného použití kódu nadtřídy umožňuje dědičnost definici generického kódu prostřednictvím mechanismu polymorfismu.
- Příklad
Pokud již v programu existuje třída, MezzoDiTrasportokterá má jako vlastnost údaje o poloze, rychlosti, cíli a užitečném zatížení, a je potřeba nová třída Aereo, je možné ji vytvořit přímo z objektu MezzoDiTrasportodeklarováním třídy typu Aereo, který dědí z objektu. MezzoDiTrasportoa také přidání atributu, který identifikuje nadmořskou výšku plavby , s výhodou, že nová třída získá všechny členy definované v MezzoDiTrasportosamotném faktu, že jde o podtřídu.
Podtypování
I když koncepčně existují dobře výrazné rozdíly, mechanismus dědičnosti mezi třídami ( podtřídění ), prostřednictvím mechanismu polymorfismu inkluzí, umožňuje objektově orientovaným jazykům modelovat dědičnost mezi typy ( podtypování ).
Podle Liskovova substitučního principuS je typ podtypem toho T, kdy je možné nahradit všechny instance in Tinstancemi, při kterých je Szachováno fungování programu.
S příslušnými opatřeními je možné vytvořit vztah mezi třídou a podtřídou, který také respektuje omezení vztahu typu a podtypu. Ze syntaktického hlediska to vyžaduje, aby všechny metody nadtřídy byly přítomny v podtřídě a aby jejich příslušné signatury byly kompatibilní. V důsledku toho může podtřída, která chce definovat podtyp, potlačit metody nadtřídy, ale nemůže je odstranit. Signaturu metody lze upravit pouze částečně, s ohledem na omezení změn parametrů s ohledem na řetězec dědičnosti.
Respektování syntaktických omezení však samo o sobě nestačí k zajištění respektování Liskovovy podmínky: předefinování metod nebo přeřazení atributů by ve skutečnosti mohlo ohrozit kompatibilitu za běhu.
V mnoha jazycích se při definování podtřídy můžete rozhodnout odstranit nebo změnit vlastnosti přístupu zděděné metody. V tomto případě operace podtřídění neodpovídá operaci podtypování . Některé objektově orientované jazyky, zejména Sather , explicitně rozdělují podtřídy a podtypování na syntaktické úrovni.
V jazycích se statickým a explicitním typováním je podtypování podporováno prostřednictvím polymorfismu zahrnutím podtříd: stejná proměnná může odkazovat na objekt typu, pro který byla deklarována, nebo na typy od něj odvozené. Typ objektu identifikovaného proměnnou je proto definován za běhu ( dynamická vazba ) a lze jej během provádění programu změnit.
Polymorfismus
V objektově orientovaném programování označuje název polymorfismus zahrnutím skutečnost, že stejný spustitelný kód lze použít s instancemi různých tříd, které mají společnou nadtřídu .
Dynamická vazba nebo horizontální polymorfismus
Polymorfismus je zvláště užitečný, když je verze metody, která má být provedena, vybrána na základě typu objektu skutečně obsaženého v proměnné za běhu (spíše než v době kompilace ). Tato funkce se nazývá dynamická vazba (nebo pozdní vazba) a je podporována nejoblíbenějšími objektově orientovanými programovacími jazyky.
Pokud má proměnná typu Adva podtypy (podtřídy) Ba C, z nichž oba přepisují metodu m(), objekt obsažený v proměnné může být typu A, Bnebo C, a když je metoda vyvolána na proměnné m(), verze odpovídající typu objektu je provedené v dané době obsažené v proměnné.
Abychom se vrátili k předchozímu příkladu, předpokládá se, že Aereoosoba musí čelit mnohem složitějším postupům příjezdu a odjezdu, než je tomu u běžného nákladního vozidla, jak tomu ve skutečnosti je: pak postupy arrivo()a partenza()musí být změněny ve srovnání s postupy v základní třídě. MezzoDiTrasporto. Poté je předefinujeme ve třídě Aereo, abychom získali potřebné chování (polymorfismus): v tomto okamžiku je možné ze seznamu prostředků vzít jakékoli prostředky a zavolat arrivo()nebo partenza()se nemusíte starat o to, co je objekt, se kterým se zachází. : ať už je to normální vozidlo nebo letadlo, vždy se bude chovat tak, aby odpovídalo na stejné volání správným způsobem.
Podpora dynamické vazby není nutně automatická ve všech objektově orientovaných programovacích jazycích. Například v Javě, Smalltalku, Pythonu, Ruby se dynamická vazba implicitně používá jako výchozí chování v polymorfních třídách, zatímco v C ++ je povolena vložením klíčového slova virtual do signatury příslušné metody.
Runtime podpora volání polymorfní metody vyžaduje, aby byla polymorfní proměnná spojena s implicitními metadaty, která obsahují typ dat obsažených v proměnné v daném čase nebo tabulku polymorfních funkcí.
Příklad - Dynamická vazba
Předpokládejme, že máte následující pseudo kód v Javě, kde Classe2je podtřídou Classe1:
metoda void ( vstup int ) { Class1 c ;
if ( vstup > 0 )
c = new Class1 ();
else
c = new Class2 ();
c . doSomethingDůležité ();
}
Všimněte si, faiQualcosaDiImportanteže je to metoda definovaná pomocí, Classe1ale mohla být předefinována Classe2(protože může být nutné ji vytisknout jinak). Kompilátor nemůže v době kompilace vědět, zda cse jedná o objekt spojený s třídou Classe1nebo Classe2. Prostřednictvím dynamické vazby se volba, která metoda se má skutečně propojit , bude provádět během provádění ( runtime ), kdy je metoda skutečně volána.
Vertikální polymorfismus
Výrazem vertikální polymorfismus rozumíme možnost předefinovat nebo znovu použít metody i v odvozených třídách.
OOP jazykové problémy
Některé mechanismy zahrnuté ve správě objektů způsobují režii z hlediska času a paměti, což může v určitých situacích vést k problémům s efektivitou.
Některé jazyky, jako je Java a C++ , preferují hybridní přístup před „čistým“ OOP, jako je jazyk Smalltalk , za předpokladu, že některé primitivní datové typy nejsou považovány za objekty. Výhody tohoto přístupu jsou zvláště patrné v přítomnosti numerických výpočtů; na druhou stranu, kdykoli je potřeba objekt místo primitivního typu, je nutné uchýlit se ke speciálnímu wrapperu , což může vést ke snížení výkonu.
Tento obal může být také dán automaticky samotným jazykem, jako v případě Javy nebo C # , prostřednictvím automatické konverze zvané „autoboxing“. Umožňuje vkládat hodnoty primitivních typů (např. celá čísla, znaky) dovnitř objektů a poté volat části kódu, které by chtěly objekty, aniž by bylo nutné explicitně psát instrukce pro vytvoření objektu, který hodnotu uzavírá. Takové škatulkování řeší problém psaní obálky ručně, ale výkonnostní hit samozřejmě zůstává.
Další kritiky OOP se týkají větší strukturální složitosti ve srovnání s procedurálními jazyky, tváří v tvář omezením zavedeným pro sledování objektově orientovaného paradigmatu. Existují také některé koncepční nedostatky (zejména s ohledem na podtypování), jejichž přidání do různých implementací v jazycích může způsobit problémy programátorovi. Například operace v polymorfních kontextech není zaručena, když jsou metody předefinovány v řetězci dědičnosti. Kromě toho může změna definic v základních třídách vést ke kaskádovým chybám v podtřídách ( problém křehké základní třídy ).
Poznámky
- ^ Tyto mechanismy lze také simulovat v jazycích, které nejsou považovány za objektově orientované, pokud jsou při psaní textu programu přijaty jiné konstrukce a respektovány určité konvence.
Bibliografie
- Úvod do objektově orientovaného programování - První část ( JPG ), v MCmicrocomputer , č. 101, Řím, Technimedia, listopad 1990, str. 272-275, ISSN 1123-2714
- Úvod do objektově orientovaného programování - Druhá část ( JPG ), v MCmicrocomputer , č. 102, Řím, Technimedia, prosinec 1990, str. 241-245, ISSN 1123-2714
Související položky
- Objektově orientovaný design
- Programování událostí
- Aspektově orientované programování
- Objektově orientovaná databáze
- Zkopírujte objekt
- Unifikovaný Modelovací Jazyk
Externí odkazy
- programování objektů , na Sapienza.it , De Agostini .
- ( EN ) Objektově orientované programování , v Encyclopedia Britannica , Encyclopædia Britannica, Inc.
- bluej: Open source vývojové prostředí pro výuku objektově orientovaného programování (v Javě) , na bluej.org .
- Průvodce objektově orientovaným programováním Průvodce kromě toho, že poskytuje základní teorii OOP, je plný praktických příkladů ve všech jazycích, které weboví vývojáři nejčastěji používají: od C # přes Actionscript až po Javu a Python.