As classes aninhadas são sub-classificadas?

9

Não estou tentando dizer que sei algo que todo mundo não conhece, mas tenho resolvido cada vez mais designs com o uso de classes aninhadas, por isso estou curioso para ter uma idéia da aceitabilidade de usar isso aparentemente raramente usado mecanismo de design.

Isso me leva à pergunta: estou seguindo um caminho inerentemente ruim por razões que vou descobrir quando voltarem para me morder, ou as aulas aninhadas talvez sejam subestimadas?

Aqui estão dois exemplos para os quais eu apenas os usei: https://gist.github.com/3975581 - o primeiro me ajudou a manter juntos as coisas hierárquicas firmemente repetidas, o segundo me permitiu dar acesso aos membros protegidos aos trabalhadores ...

Anodeto de Aaron
fonte
Eu só quero dizer obrigado pelas respostas / percepções - não tenho certeza como escolher uma resposta, então eu vou deixá-lo enquanto eu meditar sobre o conselho que eu tenho e revisitar ...
Aaron Anodide

Respostas:

6

Eu não chamaria isso de "mecanismo de design raramente usado" - pelo menos não universalmente: embora existam lojas em que alguns colaboradores possam desaprovar o uso de classes aninhadas, esse não é um recurso obscuro.

Embora a existência de classes com visibilidade de montagem e a introdução de lambdas tenha reduzido significativamente a necessidade de classes aninhadas * , elas continuam sendo uma opção de design válida. Embora exista alguma sobreposição com classes internas dentro de um espaço para nome, o recurso de classes aninhadas é único, permitindo ocultar uma classe inteiramente dentro de outra classe.


* O uso de um recurso semelhante em Java é muito maior, porque outras alternativas disponíveis em C # não existem em Java.

dasblinkenlight
fonte
Então, é bom ocultar uma classe inteiramente em outra classe, de acordo com a essência do design do OOP?
Maxood 14/09/16
11
@ Maxood É bom esconder uma classe, se você puder ocultá-la. O usuário da sua API deve saber o mínimo possível sobre a maneira como sua API é implementada.
dasblinkenlight
3

Considere por um momento que você está escrevendo uma classe dentro de outra classe, que nunca será usada em nenhum outro lugar do seu programa. Porque se você o estivesse usando em outro lugar, você a tornaria uma classe pública comum, como todas as outras.

Portanto, o que deve tornar o OOP ótimo (reutilização) está ausente aqui. Além disso, o que você poderia alcançar com uma classe aninhada que não conseguiria com métodos comuns e membros privados da classe pai?

Para um padrão de software útil utilizando classes aninhadas, consulte aqui .

Robert Harvey
fonte
10
Eu nunca comprei a coisa reutilizável, pelo menos não da maneira como costuma ser colocada. (1) Chamar códigos / classes existentes (sobre os quais você parece falar e que eu costumo ver como definição de reutilização) não tem absolutamente nada a ver com OOP, é apenas modularidade básica. (2) O polimorfismo de subtipo, que é uma característica definidora do OOP, permite reutilizar o código do cliente , tornando a implementação específica irrelevante , ou seja, funciona exatamente da mesma maneira, independentemente de a classe concreta ser ou não acessível. IOW que é a reutilização que compro, mas também funciona com classes aninhadas.
11
Eu diria que também há o isolamento de namespace fornecido pela classe pai - portanto, se você quiser, as classes A e B podem ter aninhado a classe "Params" e o acesso a membros não públicos da classe que o contém. Os dois motivos não têm classes internas usadas fora da classe?
Aaron Anodide 29/10/12
@AaronAnodide Essa deve ser uma resposta sobre uma boa maneira de usar classes aninhadas. É exatamente como / por que eu os uso, ajuda a organizar o código.
Izkata
2

am I going down an inherintly bad path

Acho que no seu segundo exemplo (as subclasses de trabalhadores) você definitivamente é. Você mapeou cada subclasse para um estado específico na superclasse. Portanto, agora, toda vez que você desejar adicionar um estado à superclasse, será necessário fazer uma alteração em três locais (adicionar estado à superclasse, adicionar uma nova subclasse e alterar o construtor da classe derivada para adicionar a subclasse à lista )

O uso de classes aninhadas para acessar membros particulares parece ser um uso válido (nunca o fiz pessoalmente), mas seu caso específico não funciona aqui.

Quanto ao exemplo da parte do corpo. Como todas as classes aninhadas são públicas, você não está fazendo muito, exceto o namespace. Se essas classes crescerem para incluir mais funcionalidades, você poderá descobrir que as classes aninhadas apenas confundem as interfaces e você está vasculhando o código para encontrar algo específico. Percebo também que, como você aninhou classes, é forçado a quebrar as convenções de nomenclatura e nomear suas classes com letras minúsculas (talvez essa tenha sido uma opção). Mas esses argumentos são mais superficiais do que qualquer coisa realmente errada.

A menos, é claro, que você precise implementar um braço sem corpo. Em seguida, criar um braço, fazendo o seguinte, é confuso, porque não há corpo / torso / lado. (Observe também a caixa confusa).

arm newArm = new Body.torso.side.arm("");
nickles80
fonte
1

A única vantagem que consigo pensar em classes aninhadas é que elas podem ser tornadas privadas (ou protegidas). Eu diria que, neste caso, as classes aninhadas podem ajudá-lo a encapsular a funcionalidade se uma classe tiver a intenção de ser usada pela classe externa e somente por ela.

Bok McDonagh
fonte
1

Na minha experiência, classes aninhadas

  • Voltei para me assombrar
  • Foram usadas quando eu queria cortar cantos
  • Tornou o teste um pesadelo
  • Teve um impacto negativo na separação de preocupações e no design geral

Deu uma breve olhada na sua turma e imediatamente acho que:

  • É doloroso olhar para ele, porque a classe é enorme
  • Não consigo testar "dedos" sem criar praticamente todo o corpo
  • Não posso ter várias implementações de tronco. Não parece tão óbvio no contexto do "corpo humano", mas em um cenário diferente isso se tornaria óbvio.

Por que não separar sua classe em várias classes e fornecer espaços de nome separados. Por exemplo

WindowsGame1.PhysicalModel.UpperBody
WindowsGame1.PhysicalModel.LowerBody
WindowsGame1.PhysicalModel.UpperBody.Arms
CodeART
fonte