edytuj: Trochę dłużej czytając faq Podoba mi się pomysł przeciążania operatora << >> i dodawania go jako przyjaciela tych klas, jednak nie jestem pewien, jak to nie przerywa enkapsulacji
Jak przerwałoby to enkapsulację?
Przerywasz enkapsulację, gdy zezwalasz na nieograniczony dostęp do elementu danych. Rozważ następujące klasy:
class c1 {
public:
int x;
};
class c2 {
public:
int foo();
private:
int x;
};
class c3 {
friend int foo();
private:
int x;
};
c1
jest oczywiście nie obudowane. Każdy może w nim czytać i modyfikować x
. Nie mamy możliwości egzekwowania jakiejkolwiek kontroli dostępu.
c2
jest oczywiście zamknięty. Nie ma publicznego dostępu do x
. Wszystko, co możesz zrobić, to wywołać foo
funkcję, która wykonuje pewne znaczące operacje na klasie .
c3
? Czy to jest mniej zamknięte? Czy pozwala na nieograniczony dostęp x
? Czy umożliwia dostęp do nieznanych funkcji?
Nie. Pozwala dokładnie jednej funkcji na dostęp do prywatnych członków klasy. Tak jak c2
zrobiłem. I podobnie c2
, jedyną funkcją, która ma dostęp, nie jest „jakaś losowa, nieznana funkcja”, ale „funkcja wymieniona w definicji klasy”. Podobnie jak c2
widzimy, po prostu patrząc na definicje klas, pełną listę osób, które mają dostęp.
Jak dokładnie jest to mniej zamknięte? Ta sama ilość kodu ma dostęp do prywatnych członków klasy. I każdy, kto ma dostęp, jest wymieniony w definicji klasy.
friend
nie przerywa enkapsulacji. To sprawia, że niektórzy programiści Java czują się niekomfortowo, ponieważ kiedy mówią „OOP”, w rzeczywistości mają na myśli „Java”. Kiedy mówią „Encapsulation”, nie oznacza to „członkowie prywatne muszą być chronione przed arbitralnymi dostępów”, ale „klasy Java, gdzie funkcjonuje tylko możliwość dostępu do prywatnych członków są członkowie klasy”, choć jest to kompletny nonsens dla kilka powodów .
Po pierwsze, jak już pokazano, jest to zbyt restrykcyjne. Nie ma powodu, dla którego metody znajomych nie powinny robić tego samego.
Po drugie, nie jest to wystarczająco restrykcyjne . Rozważ czwartą klasę:
class c4 {
public:
int getx();
void setx(int x);
private:
int x;
};
To, zgodnie z wyżej wspomnianą mentalnością Javy, jest doskonale zamknięte.
A jednak pozwala absolutnie każdemu czytać i modyfikować x . Jak to w ogóle ma sens? (wskazówka: nie ma)
Konkluzja: Hermetyzacja polega na możliwości kontrolowania, które funkcje mogą uzyskiwać dostęp do członków prywatnych. To nie o dokładnie gdzie znajdują się definicje tych funkcji.