Principy objektově orientovaného programování. Objektově orientované programování

Všechny objektově orientované jazyky používají tři základní principy objektově orientovaného programování:

  • Zapouzdření. Jak tento jazyk skrývá vnitřní rysy implementace objektu?
  • Dědictví. Jak tento jazyk umožňuje opětovné použití kódu?
  • Polymorfismus. Jak daný jazyk umožňuje jednotnou interpretaci souvisejících objektů?

Prvním principem OOP je zapouzdření. Zapouzdření je programovací mechanismus, který spojuje kód a data, s nimiž manipuluje, chrání je před externím přístupem a zneužitím a skrývá detaily implementace pomocí jazyka. Řekněme například, že používáme třídu, která reprezentuje objekty jako Pen. Taková třída zapouzdřuje vnitřní schopnost objektů kreslit body, čáry a tvary různé tloušťky a barev. Princip zapouzdření zjednodušuje programovací úlohu v tom smyslu, že již není třeba se starat o četné řádky kódu, které za scénou vykonávají práci třídy per. Vše, co je potřeba, je vytvořit instanci třídy per a interagovat s ní voláním jejích funkcí.

Jedním z důležitých aspektů zapouzdření je ochrana dat. V ideálním případě by data charakterizující stav objektu měla být definována jako uzavřená a nepřístupná pro vnější prostředí. V tomto případě bude vnější prostředí objektu nuceno vyžádat si právo na změnu nebo čtení odpovídajících hodnot. Koncept zapouzdření tedy odráží obecné pravidlo, že datová pole objektu by neměla být přímo přístupná z veřejného rozhraní. Pokud uživatel potřebuje změnit stav objektu, musí to udělat ne přímo, ale nepřímo pomocí funkcí čtení ( získat()) a modifikace ( soubor()). V C# je přístupnost dat implementována na úrovni syntaxe pomocí klíčových slov veřejnost, soukromé, chráněný, A chráněný vnitřní.

V rámci objektu lze kód, data nebo kód i data uzavřít pro jiné objekty nebo otevřít. Proprietární kód a data jsou známá a přístupná z jiné části pouze tohoto objektu (tj. pouze pro samotný objekt). K proprietárnímu kódu a datům proto nelze přistupovat z části programu, která existuje mimo objekt.

Dalším principem OOP je dědictví , což znamená schopnost jazyka poskytnout konstrukci definic nových tříd na základě definic tříd existujících. Dědičnost v podstatě umožňuje rozšířit chování základní třídy (také nazývané rodičovská třída) vytvořením podtřídy (tzv derivát nebo dětská třída), která zdědí vlastnosti a funkčnost nadřazené třídy. V podstatě je tato forma dědičnosti opětovným použitím programového kódu jedné (základní) třídy v jiných (od ní odvozených) třídách. V tomto případě podřízená třída obvykle rozšiřuje možnosti základní třídy přidáním některých nových schopností, které v základní třídě nejsou. Tato forma dědičnosti se nazývá „je-a“ (to znamená být stejná, ale s většími schopnostmi).


Další formou opětovného použití kódu je model lokalizace/delegace (také známý jako lokalizační vztah „má-a“). Tento formulář se nepoužívá k vytváření vztahů mezi třídou a podtřídou. Místo toho může třída v sobě definovat nějakou proměnnou jiné třídy a vystavit některé nebo všechny své funkce vnějšímu světu. V tomto případě je třída spíše jako kontejner, který obsahuje instance jiných tříd.

Třetím principem OOP je polymorfismus . Charakterizuje schopnost jazyka interpretovat související objekty stejným způsobem. Tato funkce objektově orientovaného jazyka umožňuje základní třídě definovat sadu členů pro všechny odvozené třídy. Formálně se tento společný člen nazývá polymorfní rozhraní. Polymorfní rozhraní pro třídu je vytvořeno definováním libovolného čísla virtuální A abstraktní funkcí. Funkce virtuální třídy Může změna v odvozené třídě a abstraktní funkce může být pouze přepsat. Když odvozené třídy přepisují funkce definované v základní třídě, v podstatě přepisují způsob, jakým reagují na odpovídající požadavek. Kromě schopnosti přepisovat funkce poskytuje jazyk C# možnost využít další formu polymorfismu – přetěžování funkcí. Přetížení by mělo být považováno za další schopnost rozlišovat mezi funkcemi se stejným názvem, které se liší počtem nebo typem argumentů. Přetížení lze tedy aplikovat nejen na členské funkce třídy, ale také na globální funkce.

Vůlí osudu si musím přečíst speciální kurz o designových vzorech na univerzitě. Speciální kurz je povinný, takže studenti, kteří ke mně přicházejí, jsou velmi odlišní. Samozřejmě jsou mezi nimi i cviční programátoři. Ale bohužel většina lidí má potíže i s pochopením základních pojmů OOP.

K tomu jsem se pokusil vysvětlit základní pojmy OOP (třída, objekt, rozhraní, abstrakce, zapouzdření, dědičnost a polymorfismus) na víceméně živých příkladech.

První část níže je o třídách, objektech a rozhraních.
Druhá část ilustruje zapouzdření, polymorfismus a dědičnost

Základní pojmy OOP

Třída
Představte si, že navrhujete auto. Víte, že auto musí obsahovat motor, odpružení, dva světlomety, 4 kola atd. Víte také, že vaše auto musí umět zrychlit a zpomalit, zatáčet a couvat. A hlavně přesně víte, jak na sebe motor a kola působí, podle jakých zákonů se pohybuje vačkový a klikový hřídel a také jak jsou navrženy diferenciály. Jste si jisti svými znalostmi a pusťte se do navrhování.

Popisujete všechny části, které tvoří vaše auto, a také to, jak tyto části na sebe vzájemně působí. Navíc popisujete, co musí uživatel udělat, aby auto zabrzdilo nebo rozsvítilo dálková světla. Výsledkem vaší práce bude skica. Právě jste vyvinuli to, čemu se říká OOP Třída.

Třída je způsob popisu entity, který definuje stav a chování, které na tomto stavu závisí, a také pravidla pro interakci s touto entitou (smlouvou).

Třídu lze z programátorského hlediska považovat za soubor dat (pole, atributy, členy třídy) a funkcí pro práci s nimi (metody).

Z hlediska struktury programu je třída komplexní datový typ.

V našem případě třída zobrazí entitu – auto. Atributy třídy budou motor, odpružení, karoserie, čtyři kola atd. Metody třídy budou „otevřít dveře“, „sešlápnout plynový pedál“ a také „načerpat část benzínu z plynové nádrže do motoru“. První dvě metody jsou dostupné pro provádění jinými třídami (zejména třídou „Driver“). Ten popisuje interakce v rámci třídy a není přístupný uživateli.

Od nynějška, i když je slovo „uživatel“ spojeno se Solitaire a Microsoft Word, budeme jako uživatele označovat programátory, kteří používají vaši třídu, včetně vás. Osobu, která je autorem třídy, budeme říkat vývojář.

Objekt
Odvedli jste skvělou práci a stroje vyvinuté podle vašich výkresů sjíždějí z montážní linky. Tady jsou, stojící v úhledných řadách na továrním dvoře. Každý z nich přesně opakuje vaše kresby. Všechny systémy spolupracují přesně tak, jak jste navrhli. Ale každé auto je jedinečné. Všechny mají čísla karoserie a motoru, ale tato čísla jsou všechna odlišná, auta se liší barvou a některá mají dokonce odlitky místo vyražených kol. Tato auta jsou v podstatě předměty vaší třídy.

objekt (instance) je individuální zástupce třídy, který má specifický stav a chování, které jsou zcela určovány třídou.

Jednoduše řečeno, objekt má specifické hodnoty atributů a metody, které fungují na těchto hodnotách na základě pravidel definovaných ve třídě. Pokud je v tomto příkladu třída nějaké abstraktní auto ze „světa myšlenek“, pak je objektem konkrétní auto stojící pod vašimi okny.

Rozhraní
Když přistoupíme ke kávovaru nebo usedneme za volant, začneme s nimi komunikovat. K interakci obvykle dochází pomocí určité sady prvků: štěrbiny pro přijímání mincí, tlačítka pro výběr nápoje a přihrádky na výdej sklenice v kávovaru; volant, pedály, řadicí páka v autě. Vždy existuje nějaká omezená sada ovládacích prvků, se kterými můžeme komunikovat.

Rozhraní je sada metod tříd, které jsou dostupné pro použití jinými třídami.

Je zřejmé, že rozhraním třídy bude množina všech jejích veřejných metod spolu se sadou veřejných atributů. Rozhraní v podstatě specifikuje třídu a jasně definuje všechny možné akce s ní.
Dobrým příkladem rozhraní je přístrojová deska automobilu, která umožňuje vyvolat metody jako zrychlení, brzdění, zatáčení, řazení, rozsvícení světlometů atd. Tedy všechny úkony, které může jiná třída (v našem případě řidič) provádět při interakci s vozem.

Při popisu rozhraní třídy je velmi důležité najít rovnováhu mezi flexibilitou a jednoduchostí. Třída s jednoduchým rozhraním se bude snadno používat, ale vyskytnou se problémy, které nedokáže vyřešit. Zároveň, pokud je rozhraní flexibilní, pak se s největší pravděpodobností bude skládat z poměrně složitých metod s velkým počtem parametrů, které vám umožní udělat hodně, ale jeho použití bude spojeno s velkými obtížemi a rizikem chyba, něco popleteného

Příkladem jednoduchého rozhraní může být automobil s automatickou převodovkou. Jeho obsluhu si velmi rychle osvojí každá blondýnka, která absolvovala dvoutýdenní řidičský kurz. Na druhou stranu, abyste zvládli řízení moderního osobního letadla, potřebujete několik měsíců nebo dokonce let tvrdého tréninku. Nechtěl bych být na palubě Boeingu pilotovaného někým, kdo má dva týdny letových zkušeností. Na druhou stranu nikdy nedostanete auto, které by vzlétlo a odletělo z Moskvy do Washingtonu.

Programovací paradigmata

Objektově orientované programování (OOP)- metodologie programování založená na reprezentaci programu jako kolekce objektů, z nichž každý je instancí určité třídy a třídy tvoří hierarchii dědičnosti.

Je třeba poznamenat následující důležité části této definice: 1) objektově orientované programování používá jako hlavní logické stavební bloky spíše objekty než algoritmy; 2) každý objekt je instancí určité třídy; 3) třídy tvoří hierarchie. Program je považován za objektově orientovaný pouze tehdy, jsou-li splněny všechny tři specifikované požadavky. Zejména programování, které nepoužívá dědičnost, se nenazývá objektově orientované, ale programování s abstraktními datovými typy.

Encyklopedický YouTube

    1 / 5

    ✪ Objektově orientované programování v roce 2019

    ✪ Objektově orientovaný design Část 1 – Jak jsou navrhovány třídy

    ✪ Základní principy objektově orientovaného programování. Co je OOP a proč je potřeba?

    ✪ Základy OOP v C++

    ✪ Objektově orientované programování. Třídy a objekty. Lekce 3

    titulky

Základní pojmy

Abstrakce dat Abstrakce znamená izolování smysluplných informací a vyloučení nedůležitých informací z úvahy. OOP bere v úvahu pouze abstrakci dat (často ji jednoduše nazývá „abstrakce“), což znamená soubor smysluplných charakteristik objektu, který je přístupný zbytku programu. Na druhé straně je integrita předmětné oblasti objektů a jejich rozhraní, stejně jako pohodlí jejich designu, zajištěna dědičností.

Klasifikace podtypů OOP

Luca Cardelli a Martin Abadie vytvořili teoretické zdůvodnění OOP a klasifikaci založenou na tomto zdůvodnění. Poznamenávají, že pojmy a kategorie, které identifikovali, se nenacházejí společně ve všech objektově orientovaných jazycích, většina jazyků podporuje pouze podmnožiny teorie a někdy i zvláštní odchylky od ní.

Nejvýraznější rozdíly v projevu ukazatelů kvality mezi jazyky různých typů:

  • V běžných jazycích jsou deklarované principy zaměřeny na zvýšení míry opětovného použití kódu, která je zpočátku nízká pro imperativní programování. V polymorfně typizovaných aplikacích znamená použití OOP konceptů naopak jeho zjevnou redukci v důsledku přechodu od parametrického polymorfismu k polymorfismu ad hoc. Dynamicky typované jazyky (Smalltalk, Python, Ruby) používají tyto principy k logické organizaci programu a jejich dopad na míru opětovného použití je obtížné předvídat – velmi záleží na disciplíně programátora. Například v CLOS jsou multimetody současně prvotřídními funkcemi, což umožňuje, aby byly současně považovány za související kvantifikovány a jako zobecněné (skutečně polymorfní).
  • Používání tradičních OO jazyků nominativní typizace, tedy přípustnost společného užívání objektů různých tříd pouze tehdy, jsou-li související vztahy mezi třídami výslovně uvedeny. Polymorfně typované jazyky se vyznačují strukturální typizace, tedy koordinace tříd mezi sebou stejným mechanismem jako koordinace čísla 5 s typem int . Dynamicky typované jazyky zde také zaujímají střední pozici.

Zobecněné zdůvodnění dynamické odeslání(včetně vícenásobného) postavil Giuseppe Castagna v polovině 90. let.

Příběh

OOP vznikl jako výsledek rozvoje ideologie procedurálního programování, kde data a podprogramy (procedury, funkce) pro jejich zpracování spolu formálně nesouvisí. Pro další rozvoj objektově orientovaného programování mají často velký význam pojmy událost (tzv. event-oriented programming) a komponenta (komponentní programování, COP).

Interakce objektů probíhá prostřednictvím. Výsledkem dalšího vývoje OOP bude zřejmě programování orientované na agenty, kde agenti- nezávislé části kódu na úrovni provádění. Agenti interagují prostřednictvím změny prostředí, ve kterém se nacházejí.

Do aspektů (v aspektově orientovaném programování) jsou z nich zapouzdřeny jazykové konstrukty, které strukturálně nesouvisí přímo s objekty, ale doprovázejí je pro jejich bezpečný (výjimečné situace, kontroly) a efektivní provoz. Předmětově orientované programování rozšiřuje koncept objektu tím, že poskytuje jednotnější a nezávislejší interakci mezi objekty. Může se jednat o přechodnou fázi mezi OOP a programováním agentů z hlediska jejich nezávislé interakce.

Prvním programovacím jazykem, který představil základní pojmy, které se později staly paradigmatem, byla Simula, ale termín „objektová orientace“ se v kontextu používání tohoto jazyka nepoužíval. V době svého vzniku v roce 1967 navrhoval revoluční myšlenky: objekty, třídy, virtuální metody atd., ale to vše nebylo současníky vnímáno jako něco grandiózního. Ve skutečnosti byla Simula „Algol s třídami“, který zjednodušil výraz v procedurálním programování mnoha složitých konceptů. Koncept třídy v Simule lze kompletně definovat prostřednictvím složení konstruktů Algol (to znamená, že třída v Simule je něco komplexního, popsaného prostřednictvím primitiv).

Pohled na programování z „nového úhlu“ (odlišného od procedurálního) navrhli Alan Kay a Dan Ingalls v jazyce Smalltalk. Zde se koncept třídy stal základní myšlenkou pro všechny ostatní konstrukce jazyka (tj. třída ve Smalltalku je primitivum, kterým jsou popsány složitější konstrukce). Byl to on, kdo se stal prvním široce používaným objektově orientovaným programovacím jazykem.

V současné době je počet aplikovaných programovacích jazyků (seznam jazyků) implementujících objektově orientované paradigma největší ve srovnání s ostatními paradigmaty. Nejběžnější jazyky v průmyslu (C++, Delphi, C#, Java atd.) ztělesňují objektový model Simula. Příklady jazyků založených na modelu Smalltalk jsou Objective-C, Python, Ruby.

Definice OOP a jeho základní pojmy

V centru OOP je koncept objekt. Objekt je entita, které lze posílat zprávy a která na ně může odpovídat pomocí svých dat. Objekt je instancí třídy. Data objektu jsou před zbytkem programu skryta. Skrytí dat se nazývá zapouzdření.

Přítomnost zapouzdření je dostatečná pro objektivitu programovacího jazyka, ale ještě neznamená, že je objektově orientovaný – to vyžaduje přítomnost dědičnosti.

Ale ani přítomnost zapouzdření a dědičnosti nečiní programovací jazyk plně objektově založeným z pohledu OOP. Hlavní výhody OOP se projeví až tehdy, když programovací jazyk implementuje podtypový polymorfismus – schopnost jednotně zpracovávat objekty s různými implementacemi za předpokladu, že existuje společné rozhraní.

Obtížnost definice

OOP má za sebou více než čtyřicetiletou historii, ale navzdory tomu stále neexistuje jasná obecně přijímaná definice této technologie. Základní principy stanovené v prvních objektových jazycích a systémech prošly významnými změnami (nebo deformacemi) a doplňky v četných implementacích následujících dob. Zhruba od poloviny 80. let se navíc termín „objektově orientovaný“ stal módním, v důsledku toho se mu stalo totéž, co o něco dříve s pojmem „strukturální“ (který se stal módou po rozšíření strukturovaného programování technologie) - uměle se „připoutal“ k jakémukoli novému vývoji, aby zajistil jejich atraktivitu. Björn Stroustrup v roce 1988 napsal, že ospravedlnění „objektové orientace“ něčeho ve většině případů vede k falešnému sylogismu: „X je dobré. Orientace objektu je dobrá. Proto"X je objektově orientovaný."

Roger King tvrdil, že jeho kočka byla objektově orientovaná. Mezi její další přednosti kočka prokazuje charakteristické chování, reaguje na zprávy, je obdařena zděděnými reakcemi a zvládá svůj vlastní, zcela nezávislý, vnitřní stav.

Obecnost mechanismu zasílání zpráv má však i druhou stránku – „plnohodnotný“ přenos zpráv vyžaduje další režii, což není vždy přijatelné. Proto tento koncept používá mnoho moderních objektově orientovaných programovacích jazyků "odeslání zprávy jako volání metody"- objekty mají externě přístupné metody, jejichž volání zajišťují interakci objektů. Tento přístup je implementován v obrovském množství programovacích jazyků, včetně C++, Object Pascal, Java, Oberon-2. To však vede k tomu, že zprávy již nejsou nezávislými objekty a v důsledku toho nemají atributy, což zužuje možnosti programování. Některé jazyky používají hybridní reprezentaci, ukazující výhody obou přístupů současně – například CLOS, Python.

Pojem virtuální metody, podporovaný těmito a dalšími moderními jazyky, se objevil jako prostředek k zajištění provádění požadovaných metod při použití polymorfních proměnných, tedy v podstatě jako pokus rozšířit schopnost volání metod implementovat část funkcí poskytovaných mechanismus zpracování zpráv.

Funkce implementace

Jak bylo uvedeno výše, v moderních objektově orientovaných programovacích jazycích je každý objekt hodnotou patřící do určité třídy. Třída je složený datový typ deklarovaný programátorem, který obsahuje:

Datová pole Parametry objektu (samozřejmě ne všechny, ale pouze ty, které jsou v programu nezbytné), určující jeho stav (vlastnosti objektu předmětové oblasti). Někdy se datová pole objektu nazývají vlastnosti objektu, což může vést k záměně. Fyzicky pole představují hodnoty (proměnné, konstanty) deklarované jako patřící do třídy.

Třídy mohou po sobě dědit. Potomek třídy obdrží všechna pole a metody nadřazené třídy, ale může je doplnit svými vlastními nebo přepsat existující. Většina programovacích jazyků podporuje pouze jedinou dědičnost (třída může mít pouze jednu nadřazenou třídu), pouze některé umožňují vícenásobnou dědičnost – generování třídy ze dvou nebo více nadřazených tříd. Vícenásobná dědičnost vytváří řadu problémů, jak logických, tak čistě implementačních, takže její plná podpora není rozšířená. Místo toho se v 90. letech objevil koncept rozhraní a začal být aktivně zaváděn do objektově orientovaných jazyků. Rozhraní je třída bez polí a bez implementace, která obsahuje pouze hlavičky metod. Pokud třída zdědí (nebo, jak se říká, implementuje) rozhraní, musí implementovat všechny jeho metody. Použití rozhraní poskytuje relativně levnou alternativu k vícenásobné dědičnosti.

Interakce objektů je v naprosté většině případů zajištěna vzájemným voláním metod.

Zapouzdření je zajištěno následujícími prostředky:

Řízení přístupu Protože metody tříd mohou být buď čistě interní, poskytující logiku fungování objektu, nebo externí, s jejichž pomocí objekty interagují, je nutné zajistit utajení prvních, zatímco druhé jsou přístupné zvenčí. K tomu jsou do jazyků zavedeny speciální syntaktické konstrukce, které explicitně definují rozsah každého člena třídy. Tradičně se jedná o modifikátory public, protected a private, které označují veřejné členy třídy, členy třídy přístupné v rámci třídy az tříd potomků a skryté členy přístupné pouze v rámci třídy. Konkrétní nomenklatura modifikátorů a jejich přesný význam se v různých jazycích liší. Přístupové metody Pole tříd by obecně neměla být přístupná zvenčí, protože takový přístup by umožnil libovolné změny vnitřního stavu objektů. Pole jsou proto obvykle prohlášena za skrytá (nebo jazyk obecně neumožňuje přístup k polím tříd zvenčí) a pro přístup k datům obsaženým v polích se používají speciální metody zvané přístupové metody. Takové metody buď vracejí hodnotu určitého pole, nebo do tohoto pole zapisují novou hodnotu. Při zápisu může přístupový objekt kontrolovat platnost zapisované hodnoty a v případě potřeby provádět další manipulace s daty objektu tak, aby zůstala správná (vnitřně konzistentní). Přístupové metody se také nazývají accessors (z anglického access - access), a jednotlivě - getters (anglicky get - čtení) a settery (anglicky set - psaní)., protože nepřidávají žádné nové funkce, ale pouze skrývají volání přístupových metod. Specifická jazyková implementace vlastností se může lišit. Například deklarace vlastnosti přímo obsahuje kód přístupového objektu, který je volán pouze při práci s vlastnostmi, to znamená, že nevyžaduje samostatné metody přístupového objektu, které lze volat přímo. V Delphi obsahuje deklarace vlastnosti pouze názvy metod přístupového objektu, které by měly být volány při přístupu k poli. Samotné přístupové metody jsou běžné metody s některými dalšími požadavky na podpis.

Polymorfismus je implementován zavedením pravidel do jazyka, podle kterých lze proměnné typu „class“ přiřadit objekt libovolné třídy potomka své třídy.

Návrh programu obecně

OOP je zaměřena na vývoj velkých softwarových systémů vyvíjených týmem programátorů (možná i poměrně rozsáhlých). Návrh systému jako celku, tvorbu jednotlivých komponent a jejich integraci do finálního produktu často provádějí různí lidé a není jediný specialista, který by o projektu věděl vše.

Objektově orientovaný design je zaměřen na popis struktury navrženého systému (priorita ve vztahu k popisu jeho chování, na rozdíl od funkcionálního programování), tedy ve skutečnosti na zodpovězení dvou hlavních otázek:

  • Z jakých částí se systém skládá?;
  • Jaká je odpovědnost každé z jeho částí?.

Přidělování částí probíhá tak, aby každá měla minimální objem a přesně definovaný soubor funkcí (odpovědností) a zároveň co nejméně interagovala s ostatními částmi.

Další upřesnění vede k identifikaci menších fragmentů popisu. Jak se popis a definice odpovědnosti stávají podrobnějšími, odhalují se data, která je třeba ukládat, a přítomnost agentů podobného chování, kteří se stávají kandidáty na implementaci v podobě tříd se společnými předky. Po identifikaci komponent a definování rozhraní mezi nimi lze implementaci každé komponenty provádět téměř nezávisle na ostatních (samozřejmě za dodržení příslušné technologické disciplíny).

Správná konstrukce třídní hierarchie má velký význam. Jedním ze známých problémů velkých systémů budovaných pomocí technologie OOP je tzv problém křehkosti základní třídy. Spočívá ve skutečnosti, že v pozdějších fázích vývoje, kdy byla vytvořena hierarchie tříd a na jejím základě bylo vyvinuto velké množství kódu, se ukazuje být obtížné nebo dokonce nemožné provádět jakékoli změny v kódu základní třídy hierarchie (z nichž jsou odvozeny všechny nebo mnoho tříd pracujících v systému). I když změny, které provedete, neovlivní rozhraní základní třídy, změna jejího chování může ovlivnit podřízené třídy nepředvídatelným způsobem. V případě velkého systému vývojář základní třídy prostě není schopen předvídat důsledky změn, ani neví, jak přesně se základní třída používá a na jakých vlastnostech jejího chování je správné fungování potomkových tříd závisí.

Různé OOP metodiky

Programování komponent je další fází vývoje OOP; prototypové a třídně orientované programování jsou různé přístupy k vytváření programu, které lze kombinovat a mají své výhody a nevýhody.

Komponentní programování

Komponentově orientované programování je jakousi „nadstavbou“ nad OOP, souborem pravidel a omezení zaměřených na budování velkých, vyvíjejících se softwarových systémů s dlouhou životností. Softwarový systém v této metodice je sada komponent s dobře definovanými rozhraními. Změny ve stávajícím systému se provádějí vytvořením nových součástí, které doplňují nebo nahrazují dříve existující. Při vytváření nových komponent založených na dříve vytvořených je zakázáno použití dědičnosti implementace - nová komponenta může zdědit pouze rozhraní základní. Tímto způsobem se programování komponent vyhýbá problému křehkosti základní třídy.

Prototypové programování

Prototypové programování, i když si zachovalo některé rysy OOP, opustilo základní koncepty třídy a dědičnosti.

  • Prototyp je vzorový objekt, v jehož obrazu a podobě jsou vytvořeny další objekty. Kopírované objekty mohou udržovat spojení s nadřazeným objektem a automaticky zdědit změny prototypu; tato funkce je definována v rámci konkrétního jazyka.
  • Místo mechanismu pro popis tříd a spawnovacích instancí poskytuje jazyk mechanismus pro vytváření objektu (zadáním sady polí a metod, které objekt musí mít) a mechanismus pro klonování objektů.
  • Každý nově vytvořený objekt je „instancí bez třídy“. Každý předmět se může stát prototyp- použít k vytvoření nového objektu pomocí operace klonování. Po klonování lze nový objekt upravit, zejména lze přidat nová pole a metody.
  • Klonovaný objekt se buď stane úplnou kopií prototypu, uloží všechny hodnoty svých polí a duplikuje své metody, nebo si zachová odkaz na prototyp bez zahrnutí klonovaných polí a metod, dokud nebudou upraveny. V druhém případě poskytuje mechanismus běhové prostředí delegace- pokud při přístupu k objektu samotný neobsahuje požadovanou metodu nebo datové pole, je volání předáno prototypu, z něj případně dále v řetězci.

Třídně orientované programování

Třídně orientované programování je programování zaměřené na data, kde jsou data a chování neoddělitelně propojeny. Data a chování dohromady tvoří třídu. V souladu s tím jsou v jazycích založených na konceptu „třídy“ všechny objekty rozděleny do dvou hlavních typů - tříd a instancí. Třída definuje strukturu a funkčnost (chování), které jsou stejné pro všechny instance této třídy. Instance je datový nosič – to znamená, že má stav, který se mění v souladu s chováním specifikovaným třídou. V třídně orientovaných jazycích se nová instance vytvoří prostřednictvím volání konstruktoru třídy (případně se sadou parametrů). Výsledná instance má strukturu a chování pevně zakódované její třídou.

Výkon objektového programu

Gradi Booch poukazuje na následující důvody vedoucí ke snížení výkonu programu v důsledku použití objektově orientovaných nástrojů:

Dynamické propojování metod Zajištění polymorfního chování objektů vede k nutnosti propojit metody volané programem (tedy určit, která konkrétní metoda bude volána) nikoli ve fázi kompilace, ale během provádění programu, což vyžaduje další čas. Dynamická vazba je však ve skutečnosti vyžadována pro ne více než 20 % volání, ale některé OOP jazyky ji používají neustále.

  • Značná hloubka abstrakce OOP vývoje často vede k vytváření „vícevrstvých“ aplikací, kde je výkon požadované akce objektu redukován na mnoho volání objektů nižší úrovně. V takové aplikaci je spousta volání metod a návratů metod, což přirozeně ovlivňuje výkon.
  • Dědičnost kód „rozmazává“ Kód související s „konečnými“ třídami hierarchie dědičnosti, které program obvykle používá přímo, se nachází nejen v těchto třídách samotných, ale také v jejich předchůdcích. Metody patřící do stejné třídy jsou ve skutečnosti popsány v různých třídách. To vede ke dvěma nepříjemným věcem:
Rychlost překladu se sníží, protože linker musí načíst popisy všech tříd v hierarchii.

Přes tyto nedostatky Booch tvrdí, že výhody používání OOP jsou větší. Zvýšená produktivita díky lepší organizaci OOP kódu navíc podle něj v některých případech kompenzuje dodatečné režijní náklady na organizaci fungování programu. Můžete si také všimnout, že mnoho efektů snížení výkonu lze vyhladit nebo dokonce úplně odstranit díky vysoce kvalitní optimalizaci kódu kompilátorem. Například již zmíněné snížení rychlosti přístupu k polím tříd vlivem používání přístupových metod odpadá, pokud kompilátor místo volání přístupové metody použije inline substituci (moderní kompilátory to dělají celkem sebevědomě).

Kritika OOP

Navzdory některým výtkám vůči OOP jde o paradigma, které se v současnosti používá v naprosté většině průmyslových projektů. Nelze však předpokládat, že OOP je nejlepší programovací technika ve všech případech.

Kritika OOP:

  • Ukázalo se, že mezi OOP a procedurálním přístupem není žádný významný rozdíl v produktivitě vývoje softwaru.
  • Christopher Date poukazuje na nemožnost srovnání OOP a jiných technologií, z velké části kvůli absenci přísné a obecně uznávané definice OOP.
  • Alexander Stepanov v jednom ze svých rozhovorů poukázal na to, že OOP je „metodologicky nesprávný“ a že „... OOP je prakticky stejný podvod jako umělá inteligence...“.
  • Frederick Brooks poukazuje na to, že nejobtížnější částí vytváření softwaru je „... specifikace, návrh a testování konceptuálních konstruktů, nikoli práce na vyjádření těchto konceptuálních konstruktů...“. OOP (spolu s technologiemi jako umělá inteligence, verifikace programů, automatické programování, grafické programování, expertní systémy atd.) podle něj není „stříbrnou kulkou“, která by mohla snížit složitost vývoje softwarových systémů řádově velikost. Podle Brookse „...OOP pouze snižuje zavedenou složitost ve výrazu designu. Design zůstává od přírody složitý...“
  • Edsger Dijkstra zdůraznil: „... to, co společnost ve většině případů požaduje, je elixír na všechny nemoci. Samozřejmě, že „elixír“ má velmi působivá jména, jinak bude velmi obtížné něco prodat: „Strukturální analýza a design“, „Softwarové inženýrství“, „Modely zralosti“, „Manažerské informační systémy“, „Integrovaná prostředí“ podpora projektu ", "Objektová orientace", "Reengineering obchodních procesů...".
  • Niklaus Wirth věří, že OOP není nic jiného než triviální nadstavba nad strukturovaným programováním a přehánění jeho důležitosti, vyjádřené mimo jiné v začleňování stále módnějších „objektově orientovaných“ nástrojů do programovacích jazyků, poškozuje kvalitu softwaru. se vyvíjí.
  • Patrick Killelia ve své knize „Tuning a Web Server“ napsal: „...OOP vám nabízí mnoho způsobů, jak zpomalit vaše programy...“.
  • Známý přehledový článek o problémech moderního programování OOP uvádí některé typické problémy OOP [ ] .
  • V programátorském folklóru kritika objektově orientovaného přístupu ve srovnání s funkčním přístupem využívajícím metaforu „ Podstatné jméno Království“ z eseje Steva Yeaggieho.

Pokud se pokusíme klasifikovat kritiku OOP, můžeme zdůraznit několik aspektů kritiky tohoto přístupu k programování.

Kritika OOP reklamy Myšlenka objektového programování jako nějakého druhu všemocného přístupu, který magicky eliminuje složitost programování, je kritizována, ať už explicitně vyjádřená nebo implikovaná v dílech některých OOP propagandistů, stejně jako v reklamních materiálech pro „objektově orientované“ vývojové nástroje. Jak mnozí poznamenali, včetně výše zmíněných Brooks a Dijkstra, „neexistuje žádná stříbrná kulka“ – bez ohledu na to, jakého programovacího paradigmatu se vývojář drží, vytvoření netriviálního komplexního softwarového systému vždy vyžaduje značné investice intelektuálních zdrojů a času. Žádný z nejkvalifikovanějších specialistů v oboru OOP zpravidla nepopírá opodstatněnost kritiky tohoto typu. Jedním z oblíbených předmětů kritiky je jazyk C++, který je jedním z nejběžnějších průmyslových jazyků OOP.

Objektově orientované jazyky

Mnoho moderních jazyků je speciálně navrženo pro usnadnění objektově orientovaného programování. Je však třeba poznamenat, že můžete použít techniky OOP na neobjektově orientovaný jazyk a naopak použití objektově orientovaného jazyka neznamená, že se kód automaticky stane objektově orientovaným.

Objektově orientovaný jazyk (OOL) obvykle obsahuje následující sadu prvků:

  • Deklarace tříd s poli (data - členy třídy) a metodami (funkce - členy třídy).
  • Mechanismus rozšíření třídy (dědění) je vygenerování nové třídy z existující s automatickým zahrnutím všech vlastností implementace třídy předka do složení třídy potomka. Většina OOO podporuje pouze jednu dědičnost.
  • Polymorfní proměnné a parametry funkcí (metody), umožňující přiřadit instance různých tříd stejné proměnné.
  • Polymorfní chování instancí tříd pomocí virtuálních metod. V některých OIL jsou všechny metody tříd virtuální.

Některé jazyky přidávají k určené minimální sadě určité další funkce. Mezi nimi:

  • Konstruktory, destruktory, finalizátory;
  • Vlastnosti (příslušenství);
  • Indexery;
  • Nástroje pro řízení viditelnosti komponent třídy (rozhraní nebo modifikátory přístupu, jako veřejné, soukromé, chráněné, funkce atd.).

Některé jazyky plně vyhovují principům OOP - v nich jsou všechny hlavní prvky objekty, které mají stav a přidružené metody. Příklady takových jazyků jsou Smalltalk, Eiffel. Existují hybridní jazyky, které kombinují objektový subsystém jako celek se subsystémy jiných paradigmat jako „dva nebo více jazyků v jednom“, což vám umožňuje kombinovat objektové modely s ostatními v jednom programu a rozmazávat čáru mezi objekty. -orientovaná a další paradigmata díky nestandardním schopnostem, které balancují mezi OOP a jinými paradigmaty (jako je vícenásobné odeslání, parametrické třídy, možnost manipulovat s metodami tříd jako s nezávislými objekty atd.). Příklady takových jazyků:

třída (třídy) je uživatelsky definovaný datový typ. Třída specifikuje vlastnosti a chování objektu nebo procesu ve formě datových polí a funkcí pro práci s nimi.

Základní vlastností třídy je, že podrobnosti o její implementaci jsou skryty uživatelům třídy za rozhraním. Třída jako model objektu reálného světa je tedy černá skříňka, uzavřená ve vztahu k vnějšímu světu.

Myšlenka tříd je jádrem objektově orientovaného programování (OOP). Základní principy OOP byly vyvinuty již v jazycích Simula-67 a SmallTalk, ale v té době nebyly široce používány kvůli potížím s učením a nízké efektivitě implementace.

Jsou volány konkrétní hodnoty datového typu „class“. instance třídy nebo předměty (objektů) .

Jsou volány podprogramy, které definují operace s objekty třídy metody (metody). Volání metody jsou volána zprávy (zprávy). Celá množina metod objektu se nazývá protokol zpráv, popř rozhraní zpráv (zprávarozhraní) objekt. Zpráva musí mít alespoň dvě části: konkrétní objekt, kterému má být odeslána, a název metody, která specifikuje požadovanou akci na objektu. Výpočet v objektově orientovaném programu je tedy určen zprávami předávanými z jednoho objektu do druhého.

Objekty se vzájemně ovlivňují odesíláním a přijímáním zpráv. Zpráva je požadavek na provedení akce obsahující sadu nezbytných parametrů. Mechanismus zpráv je implementován voláním příslušných funkcí. Pomocí OOP se snadno implementuje tzv. událostmi řízený model, kdy jsou data aktivní a řídí volání konkrétní části programového kódu.

OOP je programovací metoda, která rozvíjí principy strukturovaného programování a je založena na následujících abstrakcích dat:

Zapouzdření : spojení dat s procedurami a funkcemi do jednoho bloku programového kódu (data a metody pro práci s nimi jsou považovány za objektová pole).

II. Dědictví – přenos metod a vlastností z předka na potomka, bez nutnosti psát další programový kód (přítomnost instancí tříd; potomci, předci, hierarchie).

III. Polymorfismus – schopnost měnit vlastnosti a chování významově identických objektů v závislosti na jejich typu (jedno jméno pro určitou akci, která se pro objekty hierarchie provádí odlišně).

Zapouzdření

Koncept zapouzdření byl poprvé použit v jazycích, které podporují takzvaný abstraktní přístup k programování (například Modula-2). Hlavní myšlenkou abstraktního přístupu je skrýt strukturu informací o objektu před uživatelem, což mu dává možnost získat data nezbytná pro práci s objektem pouze pomocí procedur souvisejících s tímto objektem. Tato technika může výrazně zvýšit spolehlivost a přenositelnost vyvinutého softwaru. Spolehlivost se zvyšuje díky tomu, že všechny postupy pro práci s objektovými daty jsou relativně jednoduché a transparentní, což znamená, že je lze vyvíjet kvalitněji. Při změně datové struktury stačí přepracovat pouze programy přímo související s objektem a složitější programy, které tento objekt využívají, není třeba měnit. Tato okolnost zvyšuje jak spolehlivost, tak mobilitu vytvořených programů.

Dědictví

Ve druhé polovině 80. let bylo mnoha vývojářům softwaru zřejmé, že jednou z nejlepších příležitostí ke zvýšení jejich produktivity je opětovné použití programů. Je jasné, že abstraktní datové typy s jejich zapouzdřením a řízením přístupu by měly být znovu použitelné. Problém opětovného použití abstraktních datových typů je téměř ve všech případech v tom, že vlastnosti a schopnosti existujících typů nejsou pro nové použití příliš vhodné. Starší typy je potřeba alespoň minimálně upravit. Takové úpravy mohou být obtížně implementovatelné a vyžadují, aby osoba rozuměla části, ne-li celému, existujícímu kódu. Modifikace navíc v mnoha případech znamenají změny ve všech klientských programech.

Druhým problémem datově orientovaného programování je, že všechny abstraktní definice datových typů jsou nezávislé a na stejné úrovni hierarchie. To často brání tomu, aby byl program strukturován tak, aby odpovídal jeho problémové doméně. V mnoha případech původní problém obsahuje kategorie vzájemně propojených objektů, které jsou jak dědici stejných předků (tj. nacházejí se na stejné úrovni hierarchie), tak předci a dědici (tj. ve vztahu k nějaké podřízenosti mezi sebou).

Dědičnost řeší jak problémy s úpravami, které vznikají při opětovném použití abstraktního datového typu, tak problémy s organizací programu. Pokud nový abstraktní datový typ může zdědit data a funkční vlastnosti některého existujícího typu a také upravit některé z těchto entit a přidat nové entity, pak je opětovné použití značně usnadněno, aniž by bylo nutné provádět změny v opakovaně použitém abstraktním datovém typu. Programátoři mohou vzít existující abstraktní datový typ a modelovat jej podle nového typu, který splňuje nové požadavky daného problému. Předpokládejme, že váš program má abstraktní datový typ pro pole celých čísel, který zahrnuje operaci řazení. Po určité době používání je program upraven a vyžaduje nejen abstraktní datový typ pro pole celých čísel s operací řazení, ale také operaci pro výpočet aritmetického průměru pro prvky objektů, které jsou pole. Protože struktura pole je skryta v abstraktním datovém typu, bez dědičnosti je nutné typ upravit přidáním nové operace do této struktury. Při dědění není potřeba upravovat existující typ; Je možné popsat podtřídu existujícího typu, která podporuje nejen operaci řazení, ale také operaci pro výpočet aritmetického průměru.

Zavolá se třída, která je definována zděděním z jiné třídy odvozená třída (odvozenýtřída) nebo podtřída (podtřída) . Zavolá se třída, ze které je nová třída odvozena rodičovská třída (rodičtřída) nebo supertřída (supertřída) .

V nejjednodušším případě třída zdědí všechny entity (proměnné a metody) nadřazené třídy. Toto dědění lze zkomplikovat zavedením řízení přístupu k entitám nadřazené třídy.

Toto řízení přístupu umožňuje programátorovi skrýt části abstraktního datového typu před klienty. Tento typ řízení přístupu je běžný v objektově orientovaných jazykových třídách. Odvozené třídy jsou dalším druhem klientů, kterým lze udělit nebo zakázat přístup. Aby se tomu vyhovělo, některé objektově orientované jazyky zahrnují třetí kategorii řízení přístupu, často nazývanou chráněná, která se používá k udělení přístupu k odvozeným třídám a odepření přístupu k jiným třídám.

Kromě zděděných entit může odvozená třída přidávat nové entity a upravovat metody. Upravená metoda má stejný název a často stejný protokol jako metoda, jejíž je modifikací. Říká se, že nová metoda přepíše zděděnou verzi metody, která se proto nazývá přepsaná metoda. Nejobecnějším účelem náhradní metody je provést operaci, která je specifická pro objekty odvozené třídy a není specifická pro objekty nadřazené třídy.

Vývoj programu pro objektově orientovaný systém začíná definováním hierarchie tříd, která popisuje vztahy mezi objekty, které budou zahrnuty do programu řešícího problém. Čím lépe tato hierarchie tříd odpovídá problémové části, tím přirozenější bude kompletní řešení.

Nevýhodou dědičnosti jako prostředku pro usnadnění opětovného použití kódu je to, že vytváří závislosti mezi třídami v hierarchii dědičnosti. To podkopává jednu z výhod abstraktních datových typů, kterou je jejich vzájemná nezávislost. Samozřejmě ne všechny abstraktní datové typy musí být zcela nezávislé, ale obecně je nezávislost abstraktních datových typů jednou z jejich nejsilnějších pozitivních vlastností. Zvýšení znovupoužitelnosti abstraktních datových typů bez vytváření závislostí mezi některými z nich však může být obtížné, ne-li úplně beznadějné.

Polymorfismus

Třetí vlastností objektově orientovaných programovacích jazyků je typ polymorfismu poskytovaný dynamicky vazbou zpráv na definice metod. Tato vlastnost je podporována tím, že umožňuje definici polymorfních proměnných typu nadřazené třídy, které mohou také odkazovat na objekty jakékoli podtřídy této třídy. Nadřazená třída může definovat metodu, která je ve svých podtřídách přepsána. Operace definované těmito metodami jsou podobné, ale musí být specifikovány pro každou třídu v hierarchii. Když je taková metoda volána prostřednictvím polymorfní proměnné, je toto volání dynamicky spojeno s metodou v odpovídající třídě. Jedním z cílů dynamického propojování je umožnit snadnější rozšiřování softwarových systémů při jejich vývoji a údržbě. Takové programy mohou být napsány k provádění operací s objekty vlastních tříd. Tyto operace jsou přizpůsobitelné v tom smyslu, že je lze aplikovat na objekty libovolné třídy, která je odvozena ze stejné základní třídy.

Výpočetní práce v objektově orientovaných jazycích

Veškeré výpočty v plně objektově orientovaném jazyce se provádějí předáním zprávy objektu, aby zavolal jednu z jeho metod. Odpověď na zprávu je objekt, který vrací výsledek výpočtů provedených touto metodou. Spuštění programu v objektově orientovaném jazyce lze popsat jako simulaci sady počítačů (objektů) vzájemně interagujících pomocí zpráv. Každý objekt je abstrakcí počítače v tom smyslu, že ukládá data a poskytuje procesy pro manipulaci s těmito daty. Kromě toho mohou objekty odesílat a přijímat zprávy. V podstatě jde o základní vlastnosti počítače – ukládání a zpracování dat, stejně jako vysílání a příjem zpráv.

Podstatou objektově orientovaného programování je řešit problémy identifikací relevantních objektů reálného světa a zpracováním požadovaným pro tyto objekty; a následné modelování těchto objektů, jejich procesů a nezbytných vazeb mezi nimi.

Visual Component Library (VCL)

Delphi obsahuje velké množství tříd určených pro rychlý vývoj aplikací. Knihovna je napsána v Object Pascalu a má přímé spojení s vývojovým prostředím integrovaných aplikací Delphi.

Všechny třídy VCL se nacházejí na určité úrovni hierarchie a formy strom (hierarchie) tříd.

Znalost původu objektu je velkou pomocí při jeho studiu, protože dítě zdědí všechny prvky nadřazeného objektu. Pokud tedy vlastnost Caption patří do třídy TControl, pak tuto vlastnost budou mít i její potomci, například třídy TButton a TCeckBox a komponenty Button a nezávislý přepínač CheckBox. Fragment hierarchie tříd s nejdůležitějšími třídami je znázorněn na Obr.

Velkým pomocníkem při učení programovacího systému jsou kromě hierarchie tříd zdrojové kódy modulů, které se nacházejí v adresáři SOURCE hlavního adresáře Delphi.

Zapouzdření. Na jedné straně má objekt určité vlastnosti, které charakterizují jeho stav v daném okamžiku. Na druhou stranu jsou možné operace s objekty, které vedou ke změnám těchto vlastností. Přístup ke změně vlastností se provádí pouze pomocí metod vlastní této třídě objektů. Existuje metoda, tuto vlastnost daného objektu lze změnit, ale pokud žádná metoda neexistuje, nelze ji změnit. Zdá se, že metody „obklopují“ vlastnosti objektu; říkají, že vlastnosti jsou „zapouzdřeny“ v objektu. Aby bylo zajištěno zapouzdření, třída nesmí umožňovat přímý přístup ke svým datům. Zapouzdření– mechanismus pro skrytí všech vnitřních detailů objektu, které neovlivňují jeho chování.

Dědictví. Dědičnost definuje vztah mezi třídami: objekty třídy potomka mají všechny vlastnosti a metody objektů nadřazené třídy a neměly by je znovu implementovat. Tito. jeden předmět získává vlastnosti jiného předmětu a přidává k nim vlastnosti charakteristické pouze pro něj. Například,

Třída "Bod" (rodič)

Kruhová třída (nástupce)

Vlastnosti

Vlastnosti

Souřadnice (x,y)

Stěhování

Středové souřadnice (x,y)

Stěhování

Změna barvy

Změna barvy

Změna poloměru

Polymorfismus (má mnoho podob). Stejnou metodu lze použít na objekty různých tříd, ale tato metoda bude fungovat odlišně. Stejné metody lze například použít na většinu objektů ve Windows a Office: kopírování, přesouvání, přejmenování, mazání atd. Mechanismy implementace těchto metod pro různé třídy (soubor v systému Windows a dokument aplikace Word) však nejsou stejné. Polymorfismus- příležitost použití stejných metod pro objekty různých tříd, pouze implementace těchto metod bude pro každou třídu individuální.

    1. Mechanismus řízení událostí

Každá akce v OS vyvolá událost, která je odeslána jako zpráva do aplikace (např. dvojité kliknutí na dokument Word aplikaci sdělí - přestaň spát, pojďme pracovat). Aplikace analyzuje zprávu a provede příslušnou akci (stáhne a otevře dokument). Tímto způsobem fungují také aplikace vytvořené pomocí událostí řízených událostmi. Zároveň ale část práce přebírá OS. Zachytí zprávu a předají ji příslušnému objektu (například "Button"), kde pak vyvolá odpovídající událost (například "Stiskni").

V programech řízených událostmi neexistuje žádný souvislý kód, který by běžel od začátku do konce. Po spuštění takových programů nemá uživatel jasně definovanou cestu. Může kdykoli stisknout libovolné tlačítko, zadat textová data do příslušného pole, zastavit zpracování a vyvolat jiný program.

V souladu s tím, že je definován mechanismus řízení událostí, je pro každý objekt (řídicí prvky, formuláře) v systému definován seznam událostí, které se k němu vztahují. Reakce na událost může být naprogramována. Chcete-li to provést, použijte kód k vytvoření procedury událostí(postupy akcí).

Nejprve vyberte objekt - ovládací prvek uživatelského rozhraní, pro který se bude zaznamenávat program jeho akcí. Dále se zavolá seznam procedur, tedy událostí pro vybraný objekt, při kterých se na objektu provede zaznamenaný program a vybere se vhodná událost.

Název každé procedury zapsané pro objekt na formuláři udává název objektu, pro který je procedura napsána, a název vybrané události, které mohou nebo nemusí být přítomny, jsou zapsány v závorkách za názvem postupu

Několik objektů se může zúčastnit procedury události. Například samotná událost nastane u prvního objektu, v důsledku čehož druhý objekt změní hodnotu své vlastnosti a třetí implementuje metodu.




Nahoru