edit: Lendo o FAQ um pouco mais Gosto da idéia do operador << >> sobrecarregar e adicionar como amigo dessas classes, no entanto, não tenho certeza de como isso não quebra o encapsulamento
Como isso quebraria o encapsulamento?
Você quebra o encapsulamento ao permitir acesso irrestrito a um membro de dados. Considere as seguintes classes:
class c1 {
public:
int x;
};
class c2 {
public:
int foo();
private:
int x;
};
class c3 {
friend int foo();
private:
int x;
};
c1
é , obviamente, não encapsulado. Qualquer um pode ler e modificar x
nele. Não temos como impor nenhum tipo de controle de acesso.
c2
é obviamente encapsulado. Não há acesso público a x
. Tudo o que você pode fazer é chamar a foo
função, que executa alguma operação significativa na classe .
c3
? Isso é menos encapsulado? Permite acesso irrestrito ax
? Permite o acesso a funções desconhecidas?
Não. Permite precisamente uma função para acessar os membros privados da classe. Assim como c2
fez. E assim c2
, a única função que tem acesso não é "alguma função aleatória e desconhecida", mas "a função listada na definição de classe". Assim c2
, podemos ver, apenas olhando as definições de classe, uma lista completa de quem tem acesso.
Então, como exatamente isso é menos encapsulado? A mesma quantidade de código tem acesso aos membros privados da classe. E todos os que têm acesso são listados na definição de classe.
friend
não quebra o encapsulamento. Isso faz com que alguns programadores de Java se sintam desconfortáveis, porque quando dizem "OOP", na verdade querem dizer "Java". Quando eles dizem "Encapsulamento", não significam "membros privados devem ser protegidos contra acessos arbitrários", mas "uma classe Java onde as únicas funções capazes de acessar membros privados são membros da classe", mesmo que isso seja um absurdo completo para várias razões .
Primeiro, como já mostrado, é muito restritivo. Não há razão para que os métodos de amigos não devam fazer o mesmo.
Segundo, não é suficientemente restritivo . Considere uma quarta classe:
class c4 {
public:
int getx();
void setx(int x);
private:
int x;
};
Isso, de acordo com a mentalidade Java acima mencionada, é perfeitamente encapsulado.
E, no entanto, permite que qualquer pessoa leia e modifique x . Como isso faz sentido? (dica: não)
Conclusão: o encapsulamento é capaz de controlar quais funções podem acessar membros privados. É não sobre precisamente onde as definições destas funções estão localizados.