Egységbe zárás

nyelvi mechanizmus a programozási nyelvekben

Az objektumorientált programozásban (OOP) az egységbe zárás az adattagok összevonására utal, a rajtuk műveleteket végrehajtó metódusokkal, az objektum egyes összetevőihez való közvetlen hozzáférés korlátozásának érdekében.[1] Az egységbe zárást egy strukturált adatobjektum értékeinek vagy állapotának elrejtésére használják egy osztályon belül, megakadályozva a kliensek közvetlen hozzájuk férését.

Nyilvánosan elérhető eljárásokat általában az osztályban biztosítanak az állapot absztrakt eléréséhez vagy módosításához. A gyakorlatban legtöbbször az úgynevezett getter és setter metódusokat biztosítanak az értékek közvetett eléréséhez, bár ez nem sérti meg az egységbe zárást, gyakran mégis potenciálisan gyenge objektumorientált programozási (OOP) tervezési gyakorlatnak tekintik.[2] (antiminta).

Ez a mechanizmus nem egyedi az OOP-nál. Az absztrakt adattípusok, például modulok, megvalósításai az enkapszuláció hasonló formáját kínálják. A hasonlóságot a programozási nyelv szakértői magyarázták egzisztenciális típusok tekintetében.[3]

Jelentése szerkesztés

Az objektumorientált programozási nyelvekben és más kapcsolódó területeken az egységbe zárás a két kapcsolódó, de egymástól eltérő fogalom egyikére, és néha ezek kombinációjára utal:[4] [5]

  • Az objektum egyes alkotóelemeihez való közvetlen hozzáférés korlátozására létrehozott nyelvi mechanizmus.[6] [7]
  • Nyelvi konstrukció, amely megkönnyíti az adatok összekapcsolását az ezen adatokon működő eljárásokkal (vagy más függvényekkel).[1] [8]

Egyes programnyelv-kutatók és akadémikusok az első jelentést önmagában vagy a másodikkal kombinálva használják az objektumorientált programozás megkülönböztető jellemzőjeként. Míg egyes lexikális lezárásokat biztosító programozási nyelvek az egységbe zárást az objektum-orientációra merőleges nyelv jellemzőjeként tekintik.

A második definíció azt hangsúlyozza, hogy sok objektumorientált nyelvben és más kapcsolódó területen az összetevők nincsenek automatikusan elrejtve, így felülírhatóak; így az információk elrejtését külön fogalomként definiálják azok, akik a második definíciót részesítik előnyben.

Az egységbe zárás jellemzőit osztályok segítségével támogatják a legtöbb objektumorientált nyelvben, bár más alternatívák is léteznek.

Egységbe zárás és öröklődés szerkesztés

A Tervezési minták szerzői hosszasan megvitatják az öröklődés és az egységbe zárás közötti feszültséget, és kijelentik, hogy tapasztalataik szerint a fejlesztők túlságosan sokat használják az öröklődést. Azt állítják, hogy az öröklődés gyakran megtöri az egységbe zárást, mivel az öröklődés egy alosztályt hoz a szülő implementációjának részleteivel.[9] Ahogy azt a Jojó probléma leírja, az öröklődés túlzott használata miatt az enkapszuláció túl bonyolulttá és nehezen debuggolhatóvá válhat.

Információ elrejtése szerkesztés

A definíció szerint, hogy az egységbe zárás "felhasználható az adattagok és metódusok elrejtésére", azaz az objektum belső állapota általában az objektumon kívül rejtve van. Általában csak az objektum saját eljárásai képesek közvetlenül vizsgálni vagy felülírni a mezőket. Az objektum belső felépítésének elrejtése megvédi annak integritását, megakadályozva a felhasználókat abban, hogy érvénytelen vagy inkonzistens állapotba állítsák az elem belső értékeit. Az egységbe zárás feltételezett előnye, hogy csökkentheti a rendszer komplexitását, és ezáltal növeli a robusztusságot, lehetővé téve a fejlesztő számára, hogy korlátozza a szoftverkomponensek közötti kölcsönös függőségeket. 

Egyes nyelvek, mint a Smalltalk és a Ruby csak az objektum eljárásain keresztül engedik meg a hozzáférést, de a legtöbb más (pl. C++, C#, Delphi vagy Java) a programozónak bizonyos mértékű ellenőrzést kínál a rejtett elemek felett, általában olyan kulcsszavak segítségével, mint a public és a private.[7] Az ISO C++ szabvány a protected, a private és a public jelzőt „hozzáférési specifikációnak” nevezi, és nem "rejt el semmilyen információt". Az információk elrejtése a fejlécfájlon keresztül összekapcsolt forráskód összeállított változatának elkészítésével valósul meg.

Szinte mindig van mód az ilyen védelem felülírására– általában a reflexión keresztül (Ruby, Java, C# stb.). Néha olyan mechanizmusokkal, mint a név meghívása (Python), vagy speciális kulcsszóhasználattal, mint a friend a C++-ban.

Példák szerkesztés

Adatmezők hozzáférésének korlátozása szerkesztés

Az olyan nyelvek, mint a C++, C#, Java, PHP, Swift és Delphi, lehetőséget kínálnak az adatmezőkhöz való hozzáférés korlátozására.

Az alábbiakban bemutatunk egy példát C#-ban, amely bemutatja, hogyan lehet korlátozni az adatmezőhöz való hozzáférést egy private kulcsszó használatával:

class Program
{
    public class Account
    {
        private decimal accountBalance = 500.00m;

        public decimal CheckBalance()
        {
            return this.accountBalance;
        }
    }

    static void Main()
    {
        Account myAccount = new Account();
        decimal myBalance = myAccount.CheckBalance();

        /* This Main method can check the balance via the public
         * "CheckBalance" method provided by the "Account" class 
         * but it cannot manipulate the value of "accountBalance" */
    }
}

Az alábbiakban egy példa Java-ra :

public class Employee {
    private BigDecimal salary = new BigDecimal(50000.00);
    
    public BigDecimal getSalary() {
        return this.salary;
    }

    public static void main() {
        Employee e = new Employee();
        BigDecimal sal = e.getSalary();
    }
}

Az egységbe zárás nem objektum-orientált nyelveken is lehetséges. C-ben például egy struktúra deklarálható a nyilvános API-ban a fejlécfájlon keresztül, azon függvények számára, amelyek olyan mezőket működtetnek, amelynek adattagjai nem elérhetőek az API kliensei számára, az extern kulcsszóval.[10] [11]

// Header file "api.h"

struct Entity;          // Opaque structure with hidden members

// API functions that operate on 'Entity' objects
extern struct Entity *  open_entity(int id);
extern int              process_entity(struct Entity *info);
extern void             close_entity(struct Entity *info);
// extern keywords here are redundant, but don't hurt.
// extern defines functions that can be called outside the current file, the default behavior even without the keyword

A kliensek, átlátszatlan adattípusú objektumok kiosztására, működtetésére és elosztására hívják meg az API-függvényeket. Az ilyen típusú tartalmak csak az API-függvények számára ismertek és hozzáférhetőek; az ügyfelek nem férhetnek hozzá közvetlenül a tartalmához, állapotához. Ezeknek a függvényeknek a forráskódja határozza meg a szerkezet tényleges tartalmát:

// Implementation file "api.c"

#include "api.h"

struct Entity {
    int     ent_id;         // ID number
    char    ent_name[20];   // Name
    ... and other members ...
};

// API function implementations
struct Entity * open_entity(int id)
{ ... }

int process_entity(struct Entity *info)
{ ... }

void close_entity(struct Entity *info)
{ ... }

Névkényszerítés szerkesztés

Az alábbiakban bemutatunk egy példát a Pythonra, amely nem támogatja a különböző hozzáférési korlátozásokat. Azonban az a szokás, hogy egy olyan változót, amelynek neve előtt aláhúzás jel "_" található, privátnak kell tekinteni.[12]

class Car: 
    def __init__(self) -> None:
        self._maxspeed = 200
 
    def drive(self) -> None:
        print(f"Maximum speed is {self._maxspeed}.")
 
redcar = Car()
redcar.drive()  # This will print 'Maximum speed is 200.'

redcar._maxspeed = 10
redcar.drive()  # This will print 'Maximum speed is 10.'

Jegyzetek szerkesztés

  1. a b Rogers: Encapsulation is not information hiding. JavaWorld, 2001. május 18. (Hozzáférés: 2020. július 20.)
  2. Holub: Why Getter and Setter methods are evil. Info World. JavaWorld, 2003. szeptember 5. [2020. július 29-i dátummal az eredetiből archiválva]. (Hozzáférés: 2021. január 17.)
  3. Pierce 2002
  4. Scott, Michael Lee. Programming language pragmatics, 2, Morgan Kaufmann, 481. o. (2006). ISBN 978-0-12-633951-2 „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” 
  5. Dale, Nell B.. Programming and problem solving with Java, 2nd, Jones & Bartlett, 396. o. (2007). ISBN 978-0-7637-3402-2 
  6. Mitchell, John C.. Concepts in programming languages. Cambridge University Press, 522. o. (2003). ISBN 978-0-521-78098-8 
  7. a b Pierce, Benjamin. Types and Programming Languages. MIT Press, 266. o. (2002). ISBN 978-0-262-16209-8 
  8. Connolly, Thomas M.. Ch. 25: Introduction to Object DMBS § Object-oriented concepts, Database systems: a practical approach to design, implementation, and management, 4th, Pearson Education, 814. o. (2005). ISBN 978-0-321-21025-8 
  9. Gamma, Erich. Design Patterns. Addison-Wesley (1994. április 1.). ISBN 978-0-201-63361-0 
  10. King, K. N.. C Programming: A Modern Approach [archivált változat], 2nd, W. W. Norton & Company, 464. o. (2008. április 1.). ISBN 978-0393979503. Hozzáférés ideje: 2019. november 1. [archiválás ideje: 2020. november 11.] 
  11. King, Kim N. C programming: a modern approach. WW Norton & Company, 2008. Ch. 18, p. 464, ISBN 0393979504
  12. Bader: The Meaning of Underscores in Python. Improve Your Python Skills. (Hozzáférés: 2019. november 1.)

Fordítás szerkesztés

Ez a szócikk részben vagy egészben az Encapsulation (computer programming) című angol Wikipédia-szócikk ezen változatának fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.

Kapcsolódó szócikkek szerkesztés