Para esclarecer, o que estou perguntando é
public class A{
private/*or public*/ B b;
}
vs.
public class A{
private/*or public*/ class B{
....
}
}
Definitivamente, posso pensar em algumas razões para usar uma ou outra, mas o que realmente gostaria de ver são exemplos convincentes que mostram que os prós e os contras não são apenas acadêmicos.
object-oriented-design
class-design
EpsilonVector
fonte
fonte
Respostas:
Eles geralmente são usados quando uma classe é um detalhe de implementação interna de outra classe, e não parte de sua interface externa. Eu os vi principalmente como classes somente de dados que tornam as estruturas de dados internas mais limpas em idiomas que não possuem uma sintaxe separada para estruturas no estilo c. Às vezes, também são úteis para objetos derivados de um método altamente personalizados, como manipuladores de eventos ou threads de trabalho.
fonte
Suponha que você esteja construindo uma árvore, uma lista, um gráfico e assim por diante. Por que você deve expor os detalhes internos de um nó ou uma célula ao mundo externo?
Qualquer pessoa que utilize um gráfico ou uma lista deve confiar apenas em sua interface, não em sua implementação, pois você poderá alterá-lo um dia no futuro (por exemplo, de uma implementação baseada em array para outra baseada em ponteiro) e nos clientes que usam seu a estrutura de dados ( cada uma delas ) precisaria modificar seu código para adequá-lo à nova implementação.
Em vez disso, encapsular a implementação de um nó ou célula em uma classe interna privada oferece a liberdade de modificar a implementação a qualquer momento, sem que os clientes sejam obrigados a ajustar o código consequentemente, desde que a interface da estrutura de dados permaneça intocado.
Ocultar os detalhes da implementação da sua estrutura de dados também traz vantagens de segurança, porque se você quiser distribuir sua classe, disponibilizará apenas o arquivo de interface junto com o arquivo de implementação compilado e ninguém saberá se você está realmente usando matrizes ou ponteiros. para sua implementação, protegendo seu aplicativo de algum tipo de exploração ou, pelo menos, de conhecimento devido à impossibilidade de usar ou inspecionar seu código. Além de questões práticas, não subestime o fato de que é uma solução extremamente elegante nesses casos.
fonte
Na minha opinião, é um bom policial usar classes definidas internamente para classes usadas brevemente em uma classe para permitir uma tarefa específica.
Por exemplo, se você precisar vincular uma lista de dados que consiste em duas classes não relacionadas:
Se sua classe interna é usada por outra classe, você deve separá-la. Se sua classe interna contiver alguma lógica, você deve colocá-la em separado.
Basicamente, acho que eles são ótimos para tapar buracos em seus objetos de dados, mas são difíceis de manter se precisarem conter lógica, pois você precisará saber onde procurá-los se precisar alterá-los.
fonte
tuple.ItemX
o código não é claro.Classes internas em alguma linguagem (Java, por exemplo) têm um vínculo com um objeto da classe que os contém e podem usar seus membros sem qualificá-los. Quando disponível, é mais claro do que reimplementá-los usando outros recursos de idioma.
Classes aninhadas em outra linguagem (C ++, por exemplo) não têm esse vínculo. Você está simplesmente usando o controle de escopo e acessibilidade fornecido pela classe.
fonte
Evito classes internas em Java porque a troca a quente não funciona na presença de classes internas. Eu odeio isso porque realmente odeio comprometer o código por essas considerações, mas essas reinicializações do Tomcat se somam.
fonte
Um dos usos para a classe interna estática privada é o padrão Memo. Você coloca todos os dados que precisam ser lembrados na classe privada e os retorna de alguma função como Object. Ninguém do lado de fora não pode (sem reflexão, desserialização, inspeção de memória ...) investigá-lo / modificá-lo, mas ele pode devolvê-lo à sua classe e restaurar seu estado.
fonte
Um motivo para usar uma classe interna privada pode ser porque uma API que você está usando requer herança de uma classe específica, mas você não deseja exportar o conhecimento dessa classe para usuários da sua classe externa. Por exemplo:
Nisso, o do_my_async_op exige que um objeto do tipo retorno de chamada seja passado para ele. Esse retorno de chamada tem um público assinatura de função de membro que a API usa.
Quando do_op () é chamado de outer_class, ele usa uma instância da classe interna privada que herda da classe de retorno de chamada necessária em vez de um ponteiro para si mesmo. A classe externa tem uma referência à classe externa com o objetivo simples de desviar o retorno de chamada para o privado da classe externa função de membro do_callback .
O benefício disso é que você tem certeza de que ninguém mais pode chamar a função de membro pública "fire ()".
fonte
De acordo com Jon Skeet, em C # in Depth, o uso de uma classe aninhada era a única maneira de implementar um singleton totalmente seguro para encadeamentos preguiçosos (consulte a Quinta Versão) (até o .NET 4).
fonte
Classes privada e interna são usadas para aumentar os níveis de encapsulamento e ocultar os detalhes da implementação.
No C ++, além de uma classe privada, o mesmo conceito pode ser alcançado implementando o espaço de nome anônimo de uma classe cpp. Isso serve para ocultar / privatizar um detalhe de implementação.
É a mesma idéia que uma classe interna ou privada, mas com um nível ainda maior de encapsulamento, pois é completamente invisível fora da unidade de compilação do arquivo. Nada disso aparece no arquivo de cabeçalho ou é visível externamente na declaração da classe.
fonte