Hermetyzacja (informatyka): Różnice pomiędzy wersjami

Przejdź do nawigacji Przejdź do wyszukiwania
Usunięto możliwia rozbicie modelu na mniejsze elementy, prowadzono Wyodrębnia interfejs
[wersja przejrzana][wersja nieprzejrzana]
(Poprawione wcięcia i odstępy)
(Usunięto możliwia rozbicie modelu na mniejsze elementy, prowadzono Wyodrębnia interfejs)
== Przyczyny stosowania hermetyzacji ==
Można wyróżnić trzy główne powody wprowadzenia hermetyzacji do programowania obiektowego:
#wyodrębnia interfejs
#uodparnia tworzony model na błędy,
#lepiej oddaje rzeczywistość,
 
#umożliwia rozbicie modelu na mniejsze elementy.
=== Wyodrębnia interfejs ===
 
==== Cel ====
Głównym zdaniem wyodrębnienia interfejsu, a tym samym enkapsulacji, jest ukrycie przed użytkownikiem sposobu w jaki klasa wewnętrznie realizuje swoje zadanie. Metody i pola znajdujące się w sekcji publicznej stanowią interfejs, tj. jedyny dopuszczalny zbiór elementów klasy, którymi inne klasy mogą oddziaływać z daną klasą. Posiadanie wyodrębnionego interfejsu powoduje, że użytkownik danej klasy ma pewność, że korzystając z tych metod jest bezpieczny, tj. nie dojdzie do sytuacji w której klasa zostanie uszkodzona (np. zwolnienie pamięci pod wewnętrznym wskaźnikiem klasy). Metody interfejsowe, tj. ujawnione użytkownikowi klasy, w założeniu są absolutnie bezpieczne i korzystając tylko z nich nie można doprowadzić do nieprawidłowego stanu klasy.
 
==== Przykład ====
Posiadając zdefiniowany interfejs programista klasy ma pełną swobodę implementacji mechanizmu, w jaki klasa będzie wykonywała swoje zdanie. Jeżeli klasa ma za zadanie np. gromadzić zbiór liczb podawanych do niej pojedynczo a następnie, w dowolnym momencie, zwrócić maksimum tej kolekcji, to interfejs w żaden sposób nie narzuca programiście klasy konkretnego sposobu wykonania tej implementacji. Na przykładzie języka [[C++]], klasa może to wewnętrznie wykonywać w oparciu o składową typu <code>std::set</code> jak również <code>std::vector</code>, który każdorazowo przez zwróceniem wartości maksymalnej będzie poddawany sortowaniu. Od strony użytkownika klasy sposób implementacji nie powinien być szczególnie interesujący, a co ważniejsze, nie powinien wpływać na sposób używania klasy.
 
==== Wyodrębnianie interfejsu w językach bez wsparcia enkapsulacji ====
W językach w których nie istnieje mechanizm enkapsulacji (np. [[Python]], [[C_(język_programowania)|C]]) stosuje się wyznaczanie interfejsu poprzez konwencję nazewnictwa, tj. składowe prywatne lub chronione mają specjalny przedrostek nazwy, np. ich nazwy zaczynają się od podkreślnika. Używanie metod wewnętrznych wiąże się z ryzykiem wywołania nieprawidłowego stanu programu co może prowadzić do awarii.
 
Niech dana będzie klasa interfejsowa definiująca jedynie interfejs, czyli zbiór jedynie publicznych, abstrakcyjnych i [[Metoda_wirtualna|wirtualnych metod]]. Metody te, zgodnie z definicją metody abstrakcyjnej, nie są wytłumaczone w obrębie tej klasy, a jedynie określono, że klasa dziedzicząca po tej klasie wytłumaczyć jak każda z tych metod działa. Na przykładzie:
 
<source lang="cpp">
class Sortowacz
{
public:
virtual void dodajLiczbe(int liczba) = 0;
virtual int maksimum() const = 0;
};
</source>
 
A następnie zakładając, że mamy dwie realne implementacje <code>SortowaczNaWektorze</code> oraz <code>SortowaczNaZbiorze</code> można wykonać następujący kod:
<source lang="cpp">
int main()
{
const int tablica_rozmiar = 11;
const int[] tablica = {1,3,4,0,5,2,6,7,1,3,4};
Sortowacz* sort1 = new SortowaczNaZbiorze;
Sortowacz* sort2 = new SortowaczNaWektorze;
int indeks = 0;
while ( indeks < tablica_rozmiar )
{
sort1.dodajLiczbe( tablica[indeks] );
sort2.dodajLiczbe( tablica[indeks] );
std::cout << "Sort1: Obecne maksimum to " << sort1.maksimum() << std::endl;
std::cout << "Sort2: Obecne maksimum to " << sort2.maksimum() << std::endl;
}
delete sort1;
delete sort2;
return 0;
}
</source>
Korzyść z takiego podejścia polega na tym, że interfejs dzięki enkapsulacji całkowicie milczy o sposobie zaimplementowania klasy a dodatkowo korzystając z mechanizmu polimorfizmu można posiadać wiele wymiennych klas realizujących ten sam interfejs, a to która z nich będzie wykorzystana może być zmieniane choćby w trakcie działania programu.
 
=== Uodparnia tworzony model na błędy ===
=== Lepiej oddaje rzeczywistość ===
Przykład powyższy obrazuje wykonywane na koncie bankowym [[Operacja atomowa|operacje atomowe]] identyfikowane nazwami odpowiednimi do wykonywanej operacji, podczas gdy samo odwoływanie się w sposób bezpośredni do salda jako pewnej zmiennej nie dawałoby odwzorowania rzeczywistości reprezentowanej przez tę zmienną.
 
=== Umożliwia rozbicie modelu na mniejsze elementy ===
Dzięki stosowaniu hermetyzacji można ''budować'' modele rzeczywistości jako struktury składające z mniejszych ''modułów'', z których każdy ma pewne określone dane i określone metody wpływania na ich stan i sprawdzania go. Na przykład w tworzeniu modelu samochodu można użyć modułu silnika, który ma określony szereg danych wewnętrznych (np. opisujących jego stan w trakcie pracy) i metod wewnętrznych (np. pobranie paliwa, wywołanie reakcji, ruch wirnika). Wszystko to jednak jest nieistotne dla użytkownika (a nawet nie powinno być dostępne), który ma możliwość użycia tylko zapłonu i wyłączenia silnika.
 
{{Przypisy}}
Anonimowy użytkownik

Menu nawigacyjne