Encapsulation ( angl. encapsulation , z lat. in capsula ) - v informatice proces oddělování prvků abstrakcí, které určují její strukturu (data) a chování (metody); zapouzdření má izolovat smluvní závazky abstrakce (protokol/rozhraní) od jejich implementace. V praxi to znamená, že třída by se měla skládat ze dvou částí: rozhraní a implementace. Implementace většiny programovacích jazyků ( C++ , C# , Java a další) poskytuje mechanismus skrývání , který umožňuje rozlišit přístup k různým částem komponenty.
Zapouzdření je často považováno za koncept výlučně pro objektově orientované programování (OOP) , ale ve skutečnosti se hojně vyskytuje v jiných (viz podtypování záznamu a polymorfismus záznamů a variant ). V OOP zapouzdření úzce souvisí s principem abstrakce dat (neplést s abstraktními datovými typy, jejichž implementace poskytují zapouzdření, ale mají jiný charakter). To s sebou nese zejména rozdíly v terminologii v různých zdrojích. V komunitě C++ nebo Java je zapouzdření bez skrývání obecně považováno za méněcenné. Některé jazyky (např. Smalltalk , Python ) však implementují zapouzdření, ale vůbec neumožňují skrytí. Jiné ( Standard , OCaml ) tyto pojmy pevně oddělují jako ortogonální a poskytují je sémanticky odlišným způsobem (viz skrytí v jazyce modulu ML ).
Obecně platí, že v různých programovacích jazycích termín „zapouzdření“ označuje jeden nebo oba následující zápisy současně:
Slovo „zapouzdření“ pochází z latiny in capsula – „umístění do skořápky“. Zapouzdření lze tedy intuitivně chápat jako izolaci, uzavření něčeho cizího za účelem vyloučení vlivu na okolí, zajištění dostupnosti hlavního obsahu, zvýraznění hlavního obsahu umístěním všeho rušivého, sekundárního do nějaké podmíněné kapsle ( black box ).
Třída A zapouzdřuje vlastnosti Aa, Ab a metodu Do_Something(), představující externí rozhraní Return_Something, a, b.
Účelem zapouzdření je zajistit, aby vnitřní stav objektu byl konzistentní. V C# se pro zapouzdření používají veřejné vlastnosti a metody objektu. Proměnné by až na vzácné výjimky neměly být veřejně dostupné. Zapouzdření lze ilustrovat na jednoduchém příkladu. Předpokládejme, že potřebujeme uložit skutečnou hodnotu a její řetězcovou reprezentaci (například abychom se při častém používání nepřeváděli pokaždé). Příklad implementace bez zapouzdření je následující:
class NoEncapsulation { public double ValueDouble ; veřejný řetězec ValueString ; }Zároveň můžeme samostatně měnit jak samotnou hodnotu , tak její řetězcovou reprezentaci a v určitém okamžiku se mohou neshodovat (například v důsledku výjimky). Příklad implementace pomocí zapouzdření:
class EncapsulationExample { private double valueDouble ; soukromý řetězec valueString ; public double ValueDouble { get { return valueDouble ; } set { valueDouble = hodnota ; valueString = hodnota . ToString (); } } public string ValueString { get { return valueString ; } set { double tmp_value = Převést . ToDouble ( hodnota ); //zde může nastat výjimka valueDouble = tmp_value ; valueString = hodnota ; } } }Zde lze k proměnným valueDouble a valueString přistupovat pouze prostřednictvím vlastností ValueDouble a ValueString . Pokud se pokusíme přiřadit vlastnosti ValueString neplatný řetězec a v době převodu dojde k výjimce, pak interní proměnné zůstanou ve stejném konzistentním stavu, protože výjimka způsobí ukončení procedury.
V Delphi k vytvoření skrytých polí nebo metod stačí je deklarovat v private.
TMyClass = class private FMyField : Integer ; procedura SetMyField ( const Value : Integer ) ; function GetMyField : Integer ; public property MyField : Integer read GetMyField write SetMyField ; konec ;Pro vytvoření rozhraní pro přístup ke skrytým polím zavedlo Delphi vlastnosti .
V tomto příkladu má třída A své vlastnosti $a a $b uzavřené, aby se zabránilo poškození těchto vlastností jiným kódem, kterému je třeba udělit oprávnění pouze pro čtení.
nebo
nechť A = funkce () { // soukromé nechat _majetek ; let _privateMethod = function () { /* akce */ } // soukromá metoda // veřejné vrátit { } }nebo pomocí soukromých nemovitostí
třída A { #property ; _ # privateMethod = () => { /* akce */ } get property () { // getter vrátit toto . #property ; _ } set property ( value ) { // setter toto . # vlastnost = hodnota ; } }