Zapouzdření (programování)

konstrukce programovacích jazyků

Zapouzdření může být vysvětleno jako zabalení dat a metod do jedné komponenty. Funkce zapouzdření jsou dostupné skrze třídy ve většině objektově orientovaných programovacích jazyků. Zapouzdření rovněž umožňuje ukrytí atributů a metod v objektu pomocí stavby nepropustné zdi, která brání kód proti nechtěným změnám.

V programovacích jazycích je zapouzdření přirovnáváno k jednomu z dvou pojmů a někdy i jejich kombinací,[1][2] tedy:

  • Nástroj programovacího jazyka, který je určen pro znepřístupnění jistých komponent objektů.[3][4]
  • Konstrukce jazyka, která váže data s metodami, které pracují nad danými daty.[5][6]

Někteří experti na programovací jazyky (akademici a výzkumníci) používají první význam samostatně a nebo v kombinaci s druhým jako rozlišovací rys objektově orientovaného programování, zatímco jiní vidí zapouzdření (v jazycích, které poskytují lexikální uzávěry) jako vlastnost jazyka, která poskytuje převod ortogonální orientace na objektovou. Druhá definice je motivována faktem, že v mnohých objektově orientovaných jazycích není ukrývání komponent automatické nebo se dá přepsat, proto je tedy ukrývání informací definováno jako separátní pojem pro ty, kteří preferují druhou definici.

Zapouzdření jako metoda pro ukrývání informací editovat

Zapouzdření může být využito k ukrytí členského atributu či členské metody. Pod touto definicí, zapouzdření znamená, že interní reprezentace objektu je většinou ukrytá před vnější definicí objektu. Typicky pouze vlastní metody objektu mohou přímo nahlížet a manipulovat s členskými atributy. Některé jazyky, jako například Smalltalk a Ruby, povolují přístup pouze skrz metody, ale většina ostatních (jako je C++, C# nebo Java), nabízí programátorům určitý stupeň kontroly nad tím, co by mělo být skryté a co ne. V tomto případě se typicky využívá klíčových slov public a private[4]. Je důležité zmínit, že ISO C++ standardy specifikují tato klíčová slova (protected, private a public) jako přístupové specifikátory a že jako samotné neukrývají žádné informace. Ukrytí informací je docíleno za pomoci kompilované verze zdrojového kódu, který je propojen skrz hlavičkový soubor.

Ukrytí jakýkoliv interních informací objektu chrání jeho integritu proti uživatelům tak, aby je nebylo možné nastavit do invalidního či nekonzistentního stavu. Předpokládaná výhoda zapouzdření je ve zmenšení složitosti systému a tedy ve zvýšení robustnosti.

Jako skoro všude a vždy zde existuje cesta, jak zapouzdření obejít - obvykle skrz reflexní API (Ruby, Java, C# a další), někdy ale i skrz mechanismy mandlování (Python) či skrz speciální klíčová slova jako friend v C++.

Následuje ukázka v jazyce C#, která ukazuje, jakým způsobem se dá zakázat přístup k datovým polím pomocí využití klíčového slova private:

class Program {
	public class Ucet {
		private decimal zustatek = 500.00m;
 
		public decimal ZjistitZustatek() {
			return zustatek;
		}
	}
 
	static void Main() {
		Ucet mujUcet = new Ucet();
		decimal mujZustatek = mujUcet.ZjistitZustatek();
 
		/* Metoda Main může zjistit zůstatek na účtě skrz veřejnou (public)
 metodu "ZjistitZustatek", kterou poskytuje samotná třída "Ucet",
 ale současně nemůže manipulovat přímo s hodnotou "zustatek" */
	}
}

Následuje ukázka v jazyce Java:

public class Zamestnanec {
    private BigDecimal mzda = new BigDecimal(50000.00);
 
    public BigDecimal vratMzdu() {
        return mzda;
    }
 
    public static void main() {
        Zamestnanec e = new Zamestnanec();
        BigDecimal mzda = e.vratMzdu();
    }
}

Následuje ukázka v jazyce PHP:

class Ucet
{
    /**
     * Kolik peněz máme momentálně na účtě
     *
     * @var float
     */
    private $zustatek;
 
    /**
     * @param float $currentAccountBalance Konstruktor třídy účet
     */
    public function __construct($aktualniZustatek)
    {
        $this->zustatek = $aktualniZustatek;
    }
 
    /**
     * Poslat obnos na účet
     *
     * @param float $kolik 
     *
     * @return void
     */
    public function pridat($kolik)
    {
        $this->zustatek += $kolik;
    }
 
    /**
     * Vybrat peníze z účtu
     *
     * @param float $kolik
     *
     * @throws Exception
     * @return void
     */
    public function vybrat($kolik)
    {
        if ($this->zustatek < $kolik) {
            throw new Exception('Nelze vybrat $' . $kolik . ' z tohoto účtu, protože zůstatek je pouze $' . $this->zustatek);
        }
        $this->zustatek -= $kolik;
    }
 
    /**
     * Vrátit aktuální zůstatek
     *
     * @return float
     */
    public function vratZustatek()
    {
        return $this->zustatek;
    }
}
 
// Vytvoří nový účet se zůstatkem $500.00
$mujUcet = new Ucet(500.00);
 
// Pošleme na účet $10.24
$myAccount->pridat(10.24);
// Odebereme $4.45
$myAccount->vybrat(4.45);
 
// Současný zůstatek
$aktualniZustatek = $mujUcet->vratZustatek();
echo 'Zustatek na mem ucte: $' . $aktualniZustatek; // 505.79
 
// Kód zabraňuje rovněž vybírání více, než máme v daném účtě
$mujUcet->vybrat(600.00); // Vyhodí výjimku

Zapouzdření je rovněž možné využívat ve starších jazycích, které nejsou objektově orientované. Například v C – struktura může být deklarována ve veřejně přístupné části (hlavičkový soubor) pro množinu funkcí, které operují nad danými daty, které obsahují členské proměnné, které nejsou přístupné klientům skrz hlavičku:

// Hlavička "api.h"
 
struct Entity; // Neprůhledná struktura, která má ukryté členské proměnné
 
// Hlavičkové funkce, které operují nad strukturou Entity a jejími členy
extern struct Entity * open_entity(int id);
extern int process_entity(struct Entity *info);
extern void close_entity(struct Entity *info);

Klient pak volá hlavičkové funkce k alokování, provádění operací a dealokování struktur typu „Entity“. Obsah tohoto typu je znám a přístupný pouze implementovaným hlavičkovým funkcím. Klienti nemohou k tomuto obsahu přímo přistoupit. Následuje zdrojový kód pro funkce, které definují vlastní obsah již zmíněné struktury:

// Implementace "api.c"
 
#include "api.h"
 
// Kompletní definice struktury "Entity"
struct Entity {
    int     ent_id;         // ID
    char    ent_name[20];   // název
    ... a další členy ...
};
 
// implementace hlavičkových funkcí
struct Entity * open_entity(int id)
{ ... }
 
int process_entity(struct Entity *info)
{ ... }
 
void close_entity(struct Entity *info)
{ ... }

Historický význam editovat

Význam zapouzdření může být shrnut na následující: redukce kolizí mezi stejně pojmenovanými atributy a zabalení příbuzných metod a atributů do jedné třídy. Tento model pomáhá udržovat zdrojový kód o stovkách či tisícech řádcích kódu čitelnější a jednodušší na porozumění a práci s ním.

Obecná definice editovat

Zapouzdření je obecně jedna ze 4 základních vlastností objektově orientovaného programování. Zapouzdření spočívá ve sdružování dat s metodami, které pracují na daným datech[7]. Zapouzdření je využíváno jako mechanismus ukrývání hodnot či stavů strukturovaných dat objektu uvnitř třídy, který zamezuje neautorizovaným subjektům k přímému přístupu k daným atributům. Obvykle jsou přístupné pouze veřejně dostupné metody dané třídy (tzv. „getry“ a „setry“), které umožňují přístup k vnitřním hodnotám a které ostatní třídy využívají (volají), aby získaly či modifikovaly hodnoty v daném objektu.

Tento mechanismus není unikátní v objektově orientovaném programování. Implementace abstraktních datových typů (např. modulů) nabízí podobnou formu zapouzdření. Tato podobnost vyplývá z faktu, že se oba pojmy zakládají na matematickém fundamentu existečního typu.[8]

Reference editovat

V tomto článku byl použit překlad textu z článku Encapsulation (object-oriented programming) na anglické Wikipedii.

  1. Michael Lee Scott, Programming language pragmatics, Edition 2, Morgan Kaufmann, 2006, ISBN 0-12-633951-1, p. 481: "Encapsulation mechanisms enable the programmer to group data and the subroutines that operate on them together in one place, and to hide irrelevant details from the users of an abstraction."
  2. Nell B. Dale, Chip Weems, Programming and problem solving with Java, Edition 2, Jones & Bartlett Publishers, 2007, ISBN 0-7637-3402-0, p. 396
  3. John C. Mitchell, Concepts in programming languages, Cambridge University Press, 2003, ISBN 0-521-78098-5, p.522
  4. a b PIERCE, Benjamin. Types and Programming Languages. [s.l.]: MIT Press, 2002. ISBN 0-262-16209-1. (anglicky)  p. 266
  5. Wm. Paul Rogers, Encapsulation is not information hiding Archivováno 29. 10. 2013 na Wayback Machine., JavaWorld.com, 05/18/01
  6. Thomas M. Connolly, Carolyn E. Begg, Database systems: a practical approach to design, implementation, and management, Edition 4, Pearson Education, 2005, ISBN 0-321-21025-5, Chapter 25, "Introduction to Object DMBS", section "Object-oriented concepts", p. 814
  7. RODGERS, Wm. Paul. Encapsulation is not information hiding [online]. JavaWorld [cit. 2014-03-15]. Dostupné online. (anglicky) 
  8. Pierce (2002), Section 24.2 "Data Abstraction with Existentials"

Externí odkazy editovat

SOA Patterns.org