Estou fazendo essa pergunta porque acredito que eles fizeram isso por um motivo muito bom e que a maioria das pessoas não o usa corretamente, bem, de qualquer maneira, pela minha experiência na indústria até agora. Mas se minha teoria é verdadeira, não sei por que eles incluíram o modificador de acesso privado ...?
Acredito que, se o acesso padrão for usado corretamente, ele fornece testabilidade aprimorada enquanto mantém o encapsulamento. E também torna o modificador de acesso privado redundante.
O modificador de acesso padrão pode ser usado para fornecer o mesmo efeito, usando um pacote exclusivo para métodos que precisam ser ocultos do resto do mundo, e isso sem comprometer a testabilidade, pois os pacotes em uma pasta de teste com o mesmo capaz de acessar todos os métodos padrão declarados em uma pasta de origem.
Eu acredito que é por isso que Java usa o acesso ao pacote como 'padrão'. Mas não sei por que eles também incluíram acesso privado, tenho certeza de que há um caso de uso válido ...
Respostas:
Eu acho que eles tinham uma boa idéia do que um programador comum faria. E por programador médio, quero dizer um que não é realmente bom em programação, mas consegue o emprego de qualquer maneira porque não há bons o suficiente e são caros.
Se eles tornassem o acesso "público" o padrão, a maioria dos programadores nunca se incomodaria em usar outra coisa. O resultado seria um monte de código espaguete em todos os lugares. (Como se você está tecnicamente autorizado a chamar qualquer coisa de qualquer lugar, por que se preocupar em encapsular alguma lógica dentro de um método?)
Tornar "privado" o acesso padrão seria apenas um pouco melhor. A maioria dos programadores iniciantes simplesmente inventava (e compartilhava em seus blogs) uma regra básica de que "você precisa escrever 'público' em todos os lugares" ", e então eles reclamavam por que o Java é tão ruim que os obriga a escrever" público "em todos os lugares. E eles também produziriam muito código de espaguete.
O acesso ao pacote é algo que permite que os programadores usem suas técnicas de programação desleixada enquanto escrevem código em um pacote, mas precisam reconsiderá-lo ao criar mais pacotes. É um compromisso entre boas práticas de negócios e a realidade feia. Como: escreva um código espaguete, se você insistir, mas por favor deixe a bagunça feia dentro do pacote; pelo menos crie algumas interfaces mais agradáveis entre os pacotes.
Provavelmente, há outras razões também, mas eu não subestimaria essa.
fonte
O acesso padrão não torna o modificador de acesso privado redundante.
A posição dos designers de idiomas é refletida no tutorial oficial - Controlando o acesso aos membros de uma classe e é bastante claro (para sua conveniência, declaração relevante na citação em negrito ):
Seu apelo à testabilidade como justificativa para descartar completamente o modificador privado está errado, como evidenciado, por exemplo, pelas respostas em Novo no TDD. Devo evitar métodos privados agora?
A posição dos designers de idiomas sobre a finalidade e o uso do acesso no nível do pacote é explicada em outro tutorial oficial, Criando e usando pacotes e não tem nada em comum com a ideia de eliminar modificadores privados (para sua conveniência, declaração relevante na citação em negrito ) :
<BR> "Acho que ouvi o suficiente choramingando. Acho que está na hora de dizer alto e claro ...">
Métodos particulares são benéficos para o teste de unidade.
A nota abaixo pressupõe que você esteja familiarizado com a cobertura do código . Caso contrário, reserve um tempo para aprender, pois é bastante útil para os interessados em testes de unidade e em todos os testes.
Tudo bem, então eu tenho esse método privado, testes de unidade e análise de cobertura me dizendo que há uma lacuna, meu método privado não é coberto por testes. Agora...
O que eu ganho ao mantê-lo privado
Como o método é privado, a única maneira de prosseguir é estudar o código para aprender como ele é usado por meio de API não privada. Normalmente, esse estudo revela que o motivo da lacuna é que um cenário de uso específico está ausente nos testes.
Por uma questão de integridade, outras razões (menos freqüentes) para essas lacunas de cobertura podem ser erros na especificação / design. Não vou me aprofundar nisto aqui, para manter as coisas simples; basta dizer que, se você enfraquecer a limitação de acesso "apenas para tornar o método testável", perderá a chance de descobrir que esses erros existem.
Tudo bem, para corrigir a lacuna, adiciono um teste de unidade para o cenário ausente, repito a análise de cobertura e verifico se a lacuna desapareceu. O que eu tenho agora? Eu tenho como novo teste de unidade para uso específico de API não privada.
O novo teste garante que o comportamento esperado para esse uso não seja alterado sem aviso prévio, pois, se for alterado, o teste falhará.
Um leitor externo pode examinar esse teste e aprender como ele deve usar e se comportar (aqui, o leitor externo inclui o meu eu futuro, pois tenho a tendência de esquecer o código um mês ou dois depois de terminar).
Um novo teste é tolerante à refatoração (refatoro métodos privados? Você aposta!) O que eu fizer
privateMethod
, sempre desejarei testarnonPrivateMethod(true)
. Não importa o que eu façaprivateMethod
, não haverá necessidade de modificar o teste porque o método não é chamado diretamente.Não é ruim? Pode apostar.
O que eu perco por enfraquecer a limitação de acesso
Agora imagine que, em vez de acima, eu simplesmente enfraqueci a limitação de acesso. Eu pulo o estudo do código que usa o método e prossigo diretamente com o teste que chama my
exPrivateMethod
. Ótimo? Não!Ganho um teste para uso específico da API não privada mencionada acima? Não: não havia teste para
nonPrivateMethod(true)
antes e não existe agora.Os leitores externos têm a chance de entender melhor o uso da classe? Não. - Ei, qual é o objetivo do método testado aqui? - Esqueça, é estritamente para uso interno. - Opa.
É tolerante a refatoração? De jeito nenhum: o que quer que eu mude
exPrivateMethod
, provavelmente quebrará o teste. Renomeie, mescle com outro método, altere argumentos e teste parará de compilar. Dor de cabeça? Pode apostar!Resumindo , aderir ao método privado me traz um aprimoramento útil e confiável nos testes de unidade. Por outro lado, o enfraquecimento das limitações de acesso "para testabilidade" só me fornece um código de teste obscuro e difícil de entender, que também corre o risco permanente de ser quebrado por qualquer refatoração menor; francamente, o que recebo parece suspeito como dívida técnica .
</rant>
fonte
A razão mais provável é: tem a ver com história. O ancestral de Java, Oak, tinha apenas três níveis de acesso: privado, protegido e público.
Exceto que private em Oak era o equivalente a package private em Java. Você pode ler a seção 4.10 da Especificação de idioma da Oak (ênfase minha):
Portanto, a seu ponto, o acesso privado, como é conhecido em Java, não existia originalmente. Mas quando você tem mais do que algumas classes em um pacote, não ter private como a conhecemos agora levaria a um pesadelo de colisão de nomes (por exemplo, java.until.concurrent tem cerca de 60 classes), provavelmente o motivo pelo qual elas apresentou.
No entanto, a semântica de acesso ao pacote padrão (originalmente chamada privada) não foi alterada entre o Oak e o Java.
fonte
Há situações em que alguém deseja duas classes separadas que são mais fortemente vinculadas do que expor tudo ao público. Isso tem idéias semelhantes de 'amigos' em C ++, onde outra classe declarada como 'amigo' de outra pessoa pode acessar seus membros privados.
Se você examinar as diversas classes de classes, como o BigInteger , encontrará vários tipos de proteção padrão de pacotes em campos e métodos (tudo o que é triângulo azul na lista). Isso permite que outras classes no pacote java.math tenham acesso mais ideal às suas entranhas para operações específicas (você pode encontrar esses métodos chamados em BigDecimal - o BigDecimal é apoiado por um BigInteger e salva a reimplementação do BigInteger novamente . um problema de proteção porque java.math é um pacote selado e nenhuma outra classe pode ser adicionada a ele.
Por outro lado, há muitas coisas que são realmente privadas, como deveriam ser. A maioria dos pacotes não é selada. Sem privado, seu colega de trabalho poderia colocar outra classe nesse pacote e acessar o campo privado (não mais) e quebrar o encapsulamento.
Note-se que o teste de unidade não era algo que se pensava quando os escopos de proteção estavam sendo construídos. O JUnit (a estrutura de teste do XUnit para Java) não foi concebida até 1997 (uma narrativa da história pode ser lida em http://www.martinfowler.com/bliki/Xunit.html ). As versões Alpha e Beta do JDK foram em 1995 e o JDK 1.0 em 1996, embora os níveis de proteção não tenham sido realmente definidos até o JDK 1.0.2 (antes era possível ter um
private protected
nível de proteção).Alguns argumentam que o padrão não deve ser o nível do pacote, mas privado. Outros argumentam que não deve haver uma proteção padrão , mas tudo deve ser declarado explicitamente - alguns seguidores disso escreverão códigos como:
Observe o comentário lá.
A verdadeira razão pela qual a proteção no nível do pacote é o padrão provavelmente está perdida nas notas de design do Java (estive pesquisando e não consigo encontrar nenhum porquê artigos, muitas pessoas explicando a diferença, mas nenhuma dizendo "essa é a razão ").
Então, eu vou dar um palpite. E isso é tudo - um palpite.
Primeiro, as pessoas ainda estavam tentando descobrir o design da linguagem. Desde então, os idiomas aprenderam com os erros e sucessos de Java. Isso pode ser listado como um erro para não haver algo que precise ser definido para todos os campos.
public
, eprivate
como essas têm os maiores impactos no acesso.Assim, o privado não é padrão e, bem, tudo o resto se encaixou. O escopo padrão foi deixado como padrão. Ele pode ter sido o primeiro escopo que foi criado e no interesse da compatibilidade com versões anteriores rigorosa com código antigo, foi deixado assim.
Como eu disse, tudo isso é um palpite .
fonte
Encapsulamento é uma maneira de dizer "você não precisa pensar sobre isso".
Colocando-os em termos não técnicos.
fonte
Eu não acho que eles se concentraram nos testes, simplesmente porque os testes não eram muito comuns naquela época.
O que eu acho que eles queriam alcançar era o encapsulamento no nível do pacote. Como você sabe, uma classe pode ter métodos e campos internos e apenas expor parte dela através de membros públicos. Da mesma maneira, um pacote pode ter classes, métodos e campos internos e apenas expor parte dele. Se você pensa assim, um pacote possui uma implementação interna em um conjunto de classes, métodos e campos, juntamente com uma interface pública em outro conjunto (possivelmente parcialmente sobreposto) de classes, métodos e campos.
Os codificadores mais experientes que conheço pensam assim. Eles pegam o encapsulamento e o aplicam a um nível de abstração superior à classe: um pacote ou um componente, se você preferir. Parece-me razoável que os designers de Java já tenham maturidade em seus projetos, considerando o quão bem o Java ainda se mantém.
fonte