¿Las clases anidadas están subestimadas?

9

No estoy tratando de decir que sé algo que todos los demás desconocen, pero he estado resolviendo cada vez más diseños con el uso de clases anidadas, por lo que tengo curiosidad por tener una idea de la aceptabilidad de usar este aparentemente raramente usado Mecanismo de diseño.

Esto me lleva a la pregunta: ¿voy por un camino intrínsecamente malo por razones que descubriré cuando vuelvan a morderme, o las clases anidadas pueden ser algo subestimado?

Aquí hay dos ejemplos para los que los acabo de usar: https://gist.github.com/3975581 : el primero me ayudó a mantener juntas las cosas jerárquicas estrechamente relacionadas, el segundo me permitió dar acceso a los miembros protegidos a los trabajadores ...

Aaron Anodide
fuente
Solo quiero agradecer las respuestas / ideas: no estoy seguro de cómo elegir una respuesta, así que la dejaré mientras reflexiono sobre el consejo que recibí y volví a visitar ...
Aaron Anodide

Respuestas:

6

No lo llamaría un "mecanismo de diseño raramente utilizado", al menos, no universalmente: aunque hay tiendas en las que algunos contribuyentes pueden fruncir el ceño al usar clases anidadas, esta no es una característica oscura en absoluto.

Aunque la existencia de clases con visibilidad de ensamblaje y la introducción de lambdas ha reducido significativamente la necesidad de clases anidadas * , siguen siendo una opción de diseño válida. Aunque existe cierta superposición con las clases internas dentro de un espacio de nombres, la función de clases anidadas es única al permitirle ocultar una clase completamente dentro de otra clase.


* El uso de una función similar en Java es mucho mayor, porque otras alternativas disponibles en C # no están disponibles en Java.

dasblinkenlight
fuente
Entonces, ¿es bueno ocultar una clase completamente en otra clase según la esencia del diseño OOP?
Maxood
1
@Maxood Es bueno ocultar una clase si puedes ocultarla. El usuario de su API debe saber lo menos posible sobre la forma en que se implementa su API.
dasblinkenlight
3

Considere por un momento que está escribiendo una clase dentro de otra clase, que nunca se usará en ningún otro lugar de su programa. Porque si lo usaras en otro lugar, lo convertirías en una clase pública ordinaria, al igual que todos los demás.

Entonces, lo que se supone que hace que la POO sea excelente (reutilización) está ausente aquí. Además, ¿qué podría lograr con una clase anidada que no podría lograr con métodos ordinarios y miembros privados dentro de la clase principal?

Para un patrón de software útil que utiliza clases anidadas, mira aquí .

Robert Harvey
fuente
10
Nunca he comprado la cosa de reutilización, al menos no de la forma en que se suele poner. (1) Llamar a códigos / clases existentes (de los que parece hablar, y que generalmente veo como definición de reutilización) no tiene absolutamente nada que ver con OOP, es solo modularidad básica. (2) El polimorfismo de subtipo, que es una característica definitoria de OOP, permite la reutilización del código del cliente al hacer que la implementación específica sea irrelevante , es decir, funciona exactamente de la misma manera si la clase concreta es accesible o no. IOW que es reutilización que compro, pero también funciona con clases anidadas.
1
Yo diría que también existe el aislamiento del espacio de nombres dado por la clase principal, por lo que si lo desea, ambas clases A y B podrían haber anidado la clase "Params" y el acceso a miembros no públicos de la clase que lo contiene. ¿No son ambas razones para tener clases internas que se usan fuera de la clase?
Aaron Anodide
@AaronAnodide Esa debería ser una respuesta sobre una buena manera de usar clases anidadas. Es exactamente cómo / por qué los uso, ayuda a organizar el código.
Izkata
2

am I going down an inherintly bad path

Creo que en tu segundo ejemplo (las subclases de trabajadores) definitivamente eres. Ha asignado cada subclase a un estado específico en la superclase. Entonces, cada vez que desee agregar un estado a la superclase, deberá realizar un cambio en tres ubicaciones (agregar estado a la superclase, agregar una nueva subclase y cambiar el constructor de la clase derivada para agregar una subclase a la lista )

El uso de clases anidadas para acceder a miembros privados parece ser un uso válido (nunca lo he hecho personalmente), pero su caso específico no funciona aquí.

En cuanto al ejemplo de parte del cuerpo. Debido a que todas las clases anidadas son públicas, realmente no está haciendo mucho, excepto el espacio de nombres. Si estas clases crecen para incluir más funcionalidad, es posible que las clases anidadas desordenen las interfaces y que esté examinando el código para encontrar algo específico. También noto que debido a que ha anidado clases, se ve obligado a romper las convenciones de nomenclatura y nombrar sus clases con minúsculas (tal vez esta fue una opción). Pero estos argumentos son más superficiales que cualquier cosa realmente incorrecta.

A menos, por supuesto, que necesitaras implementar un brazo sin cuerpo. Luego, crear un brazo haciendo lo siguiente es confuso porque no hay cuerpo / torso / lado. (Observe también la carcasa confusa).

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

La única ventaja que puedo pensar de las clases anidadas es que pueden hacerse privadas (o protegidas). Yo diría que en este caso las clases anidadas pueden ayudarlo a encapsular la funcionalidad si una clase está destinada a ser utilizada por la clase externa y solo esa clase.

Bok McDonagh
fuente
1

En mi experiencia, clases anidadas

  • Volví a perseguirme
  • He sido usado cuando quería cortar esquinas
  • Hacer probar una pesadilla
  • Tuvo un impacto negativo en la separación de las preocupaciones y el diseño general

Eché un breve vistazo a tu clase, y enseguida creo que:

  • Es doloroso mirarlo porque la clase es enorme
  • No puedo probar los "dedos" sin crear casi todo el cuerpo
  • No puedo tener múltiples implementaciones de torso. No parece tan obvio en un contexto de "cuerpo humano", pero en un escenario diferente esto se volvería obvio.

¿Por qué no separar su clase en varias clases y darles espacios de nombres separados? P.ej

WindowsGame1.PhysicalModel.UpperBody
WindowsGame1.PhysicalModel.LowerBody
WindowsGame1.PhysicalModel.UpperBody.Arms
CodeART
fuente