editar: leer las preguntas frecuentes un poco más Me gusta la idea de la sobrecarga del operador << >> y agregar como amigo de esas clases, sin embargo, no estoy seguro de cómo esto no rompe la encapsulación
¿Cómo rompería la encapsulación?
Rompe la encapsulación cuando permite el acceso sin restricciones a un miembro de datos. Considere las siguientes clases:
class c1 {
public:
int x;
};
class c2 {
public:
int foo();
private:
int x;
};
class c3 {
friend int foo();
private:
int x;
};
c1
es , obviamente, no encapsulada. Cualquiera puede leer y modificar x
en él. No tenemos forma de imponer ningún tipo de control de acceso.
c2
obviamente está encapsulado. No hay acceso público a x
. Todo lo que puede hacer es llamar a la foo
función, que realiza una operación significativa en la clase .
c3
? ¿Eso está menos encapsulado? ¿Permite el acceso sin restricciones x
? ¿Permite el acceso a funciones desconocidas?
No. Permite precisamente una función para acceder a los miembros privados de la clase. Justo como lo c2
hizo. Y al igual que c2
, la función que tiene el acceso no es "un poco, función desconocida al azar", pero "la función que aparece en la definición de la clase". Al igual que c2
, podemos ver, simplemente mirando las definiciones de clase, una lista completa de quién tiene acceso.
Entonces, ¿cómo es exactamente esto menos encapsulado? La misma cantidad de código tiene acceso a los miembros privados de la clase. Y todos los que tienen acceso se enumeran en la definición de clase.
friend
No rompe la encapsulación. Hace que algunos programadores de personas Java se sientan incómodos, porque cuando dicen "OOP", en realidad quieren decir "Java". Cuando dicen "encapsulación", no quieren decir "miembros privados deben ser protegidos de accesos arbitrarias", sino "una clase Java, donde las únicas funciones capaces de miembros privados de acceso, son miembros de la clase", aunque esto no tiene ningún sentido para varias razones .
Primero, como ya se mostró, es demasiado restrictivo. No hay ninguna razón por la cual no se permita que los métodos amigos hagan lo mismo.
En segundo lugar, no es restrictiva suficiente . Considere una cuarta clase:
class c4 {
public:
int getx();
void setx(int x);
private:
int x;
};
Esto, de acuerdo con la mentalidad de Java mencionada anteriormente, está perfectamente encapsulado.
Y sin embargo, permite que absolutamente cualquier persona lea y modifique x . ¿Cómo es que aún tiene sentido? (pista: no lo hace)
En pocas palabras: la encapsulación se trata de poder controlar qué funciones pueden acceder a miembros privados. Es no sobre la forma precisa en que se encuentran las definiciones de estas funciones.