Acesse o campo privado de outro objeto na mesma classe


89
class Person 
{
   private BankAccount account;

   Person(BankAccount account)
   {
      this.account = account;
   }

   public Person someMethod(Person person)
   {
     //Why accessing private field is possible?

     BankAccount a = person.account;
   }
}

Por favor, esqueça o design. Eu sei que OOP especifica que os objetos privados são privados para a classe. Minha pergunta é: por que o OOP foi projetado de forma que campos privados tenham acesso em nível de classe e não acesso em nível de objeto ?


5
Eu acredito que o OP considera o objeto "Person" passado para "someMethod" como um objeto separado e, portanto, o método não deve ter acesso a seus membros privados ... mesmo que esteja dentro da classe "Person".
Inisheer de

1
Alguns idiomas não fazem isso (Novilíngua, por exemplo). É improvável que você obtenha uma boa resposta sobre o motivo. Você obterá respostas retroativas a partir do que foi especificado.
Tom Hawtin - tackline

O someMethodnão é válido. Não retorna nada. Deve ser void.
Nicolas Barbulesco

1
Se esse não fosse o caso, seria muito difícil escrever o construtor de cópia e o operador de atribuição imo.
rozina

Respostas:


66

Também estou um pouco curioso com a resposta.

A resposta mais satisfatória que encontrei é de Artemix em outro post aqui (estou renomeando o AClass com a classe Person): Por que ter modificadores de acesso de nível de classe em vez de nível de objeto?

O modificador privado reforça o princípio de encapsulamento.

A ideia é que o 'mundo externo' não deve fazer mudanças nos processos internos da Pessoa porque a implementação da Pessoa pode mudar com o tempo (e você teria que mudar todo o mundo externo para corrigir as diferenças na implementação - o que é quase impossível).

Quando uma instância de Person acessa os internos de outra instância de Person - você pode ter certeza de que ambas as instâncias sempre sabem os detalhes de implementação de Person. Se a lógica dos processos internos para Pessoa for alterada - tudo o que você precisa fazer é mudar o código de Pessoa.

EDITAR: Por favor, vote na resposta de Artemix. Estou apenas copiando e colando.


4
Este é provavelmente o motivo. Mas isso é uma má ideia . Isso incentiva a má prática. Um desenvolvedor que acessa um campo de Person, na classe Person, não precisa saber a implementação de toda a classe. A boa prática é usar o acessador, sem precisar saber quais operações ele realiza.
Nicolas Barbulesco

16
@NicolasBarbulesco Acho que o motivo dado na resposta é correto. Digamos, por exemplo, que você deseja implementar o equals(Object)método em uma classe Java para verificar a igualdade de um Personobjeto com outra instância de Person. Você pode permitir que o mundo externo verifique se as duas instâncias são iguais, mas pode não querer expor todos os campos privados da classe necessários para verificar a igualdade para o mundo externo usando métodos de acesso público. Ter acesso em nível de classe a privatecampos permite implementar tal método sem a necessidade induzida de implementar tais métodos públicos.
Malte Skoruppa

1
@MalteSkoruppa - Este é um bom exemplo (implementação do método equals).
Nicolas Barbulesco de

@MalteSkoruppa - No entanto, a implementação do método equalspode ser feita chamando acessadores privados.
Nicolas Barbulesco de

@NicolasBarbulesco Sim, claro, mas a questão é que, quer você use acessadores privados ou acesse diretamente campos privados para implementar o método, privateé necessário conceder acesso em nível de classe. Concordo que usar acessores geralmente é um bom hábito, embora, neste caso, seja principalmente uma questão de contexto e estilo pessoal. Observe que Joshua Bloch em Effective Java (item 8) e Tal Cohen neste artigo do Dr. Dobbs acessam diretamente campos privados em suas listagens de código ao discutir como implementar equals.
Malte Skoruppa

17

Veja a especificação da linguagem Java, Seção 6.6.1. Determinando Acessibilidade

Afirma

Caso contrário, se o membro ou construtor for declarado private, o acesso será permitido se e somente se ocorrer dentro do corpo da classe de nível superior (§7.6) que inclui a declaração do membro ou construtor.

Clique no link acima para mais detalhes. Portanto, a resposta é: Porque James Gosling e os outros autores de Java decidiram que assim seria.


15

Boa pergunta. Parece que o modificador de acesso de nível de objeto reforçaria ainda mais o princípio do Encapsulamento.

Mas na verdade é o contrário. Vamos dar um exemplo. Suponha que você queira copiar em profundidade um objeto em um construtor, se não puder acessar os membros privados desse objeto. Então, a única maneira possível é adicionar alguns acessadores públicos a todos os membros privados. Isso deixará seus objetos expostos para todas as outras partes do sistema.

Portanto, o encapsulamento não significa estar fechado para todo o resto do mundo. Significa ser seletivo sobre com quem você deseja estar aberto.


2
Esta resposta precisa ser votada! Outras respostas apenas reafirmam a 'regra', mas apenas esta realmente revela a razão por trás da regra e atinge o ponto.
mzoz

4
Mas não seria melhor ter um objeto responsável por fornecer cópias de si mesmo? Então, se você precisa de uma cópia profunda de um objeto, não importa se você é outro objeto da mesma classe ou um objeto de uma classe diferente: é o mesmo mecanismo, o.deepCopy()ou seja o que for.
Dirtside

4

Isso funciona porque você está no class Person- uma classe tem permissão para cutucar seu próprio tipo de classe. Isso realmente ajuda quando você deseja escrever um construtor de cópia, por exemplo:

class A
{
   private:
      int x;
      int y;
   public:
      A(int a, int b) x(a), y(b) {}
      A(A a) { x = a.x; y = y.x; }
};

Ou se quisermos escrever operator+e operator-para nossa aula de grande número.


Isso é algo semelhante à injeção de dependência. No qual você também pode injetar algum objeto de outra classe, onde você não pode acessar a variável privada.
Nageswaran de

Claro, se você está tentando construir uma classe A a partir de um objeto da classe B e B tem um componente privado, então A precisa ser declarado amigo ou só pode ver as partes públicas [possivelmente protegidas, se A for derivado de B ]
Mats Petersson de

Em java e .net, não existe o conceito de amigo. Nesses casos, como lidar com isso?
Nageswaran de

1

Apenas meus 2 centavos na questão de por que a semântica da visibilidade privada em Java é nível de classe em vez de nível de objeto.

Eu diria que a conveniência parece ser a chave aqui. Na verdade, uma visibilidade privada no nível do objeto teria forçado a expor métodos para outras classes (por exemplo, no mesmo pacote) no cenário ilustrado pelo OP.

Na verdade, não fui capaz de inventar nem encontrar um exemplo que mostrasse que a visibilidade no nível privado da classe (como o oferecido pelo Java) cria problemas se comparada à visibilidade no nível privado do objeto.

Dito isso, as linguagens de programação com um sistema mais refinado de políticas de visibilidade podem permitir a visibilidade do objeto no nível do objeto e no nível da classe.

Por exemplo , Eiffel oferece exportação seletiva: você pode exportar qualquer recurso de classe para qualquer classe de sua escolha, de {NENHUM} (objeto-privado) para {QUALQUER} (o equivalente a público, e também o padrão), para {PESSOA} (classe privada, veja o exemplo do OP), para grupos específicos de classes {PESSOA, BANCO}.

Também é interessante observar que em Eiffel você não precisa tornar um atributo privado e escrever um getter para evitar que outras classes atribuam a ele. Atributos públicos em Eiffel são por padrão acessíveis no modo somente leitura, então você não precisa de um getter apenas para retornar seu valor.

É claro que você ainda precisa de um setter para definir um atributo, mas pode ocultá-lo definindo-o como "atribuidor" para esse atributo. Isso permite que você, se desejar, use o operador de atribuição mais conveniente em vez da invocação do setter.


0

Porque o private modificador de acesso o torna visível apenas dentro da classe . Este método ainda está NA classe .


Minha pergunta é por que ele foi projetado como "dentro da classe", mas por que não como "apenas dentro do objeto"?
Nageswaran

Porque é assim que o java é feito.
darijan

E por que java fez assim?
Nageswaran

Java não o fez, sim os criadores do Java. Por quê? Porque eles são demais!
darijan

Os criadores de Java não farão isso sem nenhum motivo e deve haver algum motivo para fazer isso; Estou perguntando o motivo
Nageswaran

0

o privatecampo está acessível na classe / objeto em que o campo está declarado. É privado para outras classes / objetos fora daquele em que está localizado.



-1

A primeira coisa que temos que entender aqui é que tudo o que temos que fazer é seguir os princípios ops, então o encapsulamento é dizer que envolve os dados dentro do pacote (isto é, classe) e então representa todos os dados como Objetos e fáceis de acessar. portanto, se tornarmos o campo não privado, ele será acessado individualmente. e isso resulta em uma paratícia ruim.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.