Para aclarar, lo que estoy preguntando es
public class A{
private/*or public*/ B b;
}
vs.
public class A{
private/*or public*/ class B{
....
}
}
Definitivamente puedo pensar en algunas razones para usar una u otra, pero lo que realmente me gustaría ver son ejemplos convincentes que muestran que los pros y los contras no son solo académicos.
object-oriented-design
class-design
EpsilonVector
fuente
fuente
Respuestas:
Por lo general, se usan cuando una clase es un detalle de implementación interna de otra clase en lugar de una parte de su interfaz externa. Principalmente los he visto como clases de solo datos que hacen que las estructuras de datos internas sean más limpias en lenguajes que no tienen una sintaxis separada para estructuras de estilo C. También son útiles a veces para objetos altamente personalizados derivados de un método, como controladores de eventos o subprocesos de trabajo.
fuente
Supongamos que está construyendo un árbol, una lista, un gráfico, etc. ¿Por qué debería exponer los detalles internos de un nodo o una célula al mundo externo?
Cualquiera que use un gráfico o una lista solo debe confiar en su interfaz, no en su implementación, ya que es posible que desee cambiarlo algún día en el futuro (por ejemplo, de una implementación basada en matriz a una basada en puntero) y los clientes que usan su estructura de datos ( cada uno de ellos ) tendría que modificar su código para adecuarlo a la nueva implementación.
En cambio, encapsular la implementación de un nodo o una celda en una clase interna privada le da la libertad de modificar la implementación en cualquier momento que lo necesite, sin que los clientes se vean obligados a ajustar su código en consecuencia, siempre que la interfaz de su estructura de datos permanezca intacto
Ocultar los detalles de la implementación de su estructura de datos también conlleva ventajas de seguridad, ya que si desea distribuir su clase, solo pondrá a disposición el archivo de interfaz junto con el archivo de implementación compilado y nadie sabrá si realmente está utilizando matrices o punteros para su implementación, protegiendo así su aplicación de algún tipo de explotación o, al menos, conocimiento debido a la imposibilidad de mal uso o inspección de su código. Además de los problemas prácticos, no subestimes el hecho de que es una solución extremadamente elegante en tales casos.
fuente
En mi opinión, es un policía justo usar clases definidas internamente para clases que se usan brevemente en una clase para permitir una tarea específica.
Por ejemplo, si necesita vincular una lista de datos que consta de dos clases no relacionadas:
Si su clase interna es utilizada por otra clase, debe ponerla por separado. Si su clase interna contiene alguna lógica, debe ponerla por separado.
Básicamente, creo que son excelentes para tapar agujeros en sus objetos de datos, pero son difíciles de mantener si realmente tienen que contener lógica, ya que tendrá que saber dónde buscarlos si necesita cambiarlos.
fuente
tuple.ItemX
el código no está claro.Las clases internas en algún lenguaje (Java, por ejemplo) tienen un vínculo con un objeto de su clase que contiene y pueden usar sus miembros sin calificarlos. Cuando está disponible, es más claro que reimplementarlos usando otras facilidades de lenguaje.
Las clases anidadas en otro lenguaje (C ++ por ejemplo) no tienen ese vínculo. Simplemente está utilizando el alcance y el control de accesibilidad proporcionados por la clase.
fuente
Evito las clases internas en Java porque el intercambio en caliente no funciona en presencia de clases internas. Odio esto porque realmente odio comprometer el código por tales consideraciones, pero esos reinicios de Tomcat se suman.
fuente
Uno de los usos de la clase interna estática privada es el patrón Memo. Coloca todos los datos que deben recordarse en una clase privada y los devuelve desde alguna función como Object. Nadie afuera no puede (sin reflexión, deserialización, inspección de memoria ...) mirarlo / modificarlo, pero él puede devolverlo a su clase y puede restaurar su estado.
fuente
Una razón para usar una clase interna privada podría ser porque una API que está utilizando requiere herencia de una clase particular, pero no desea exportar el conocimiento de esa clase a los usuarios de su clase externa. Por ejemplo:
En esto, do_my_async_op requiere que se le pase un objeto de devolución de llamada de tipo. Esta devolución de llamada tiene una firma de función de miembro público que utiliza la API.
Cuando se llama a do_op () desde la clase externa, utiliza una instancia de la clase interna privada que hereda de la clase de devolución de llamada requerida en lugar de un puntero a sí mismo. La clase externa tiene una referencia a la clase externa con el simple propósito de desviar la devolución de llamada a la función de miembro privado do_callback de la clase externa .
El beneficio de esto es que está seguro de que nadie más puede llamar a la función miembro pública "fire ()".
fuente
Según Jon Skeet en C # en profundidad, el uso de una clase anidada era la única forma de implementar un singleton totalmente seguro para subprocesos (ver Quinta versión) (hasta .NET 4).
fuente
Las clases privadas e internas se utilizan para aumentar los niveles de encapsulación y ocultar detalles de implementación.
En C ++, además de una clase privada, se puede lograr el mismo concepto implementando el espacio de nombres anónimo de una clase cpp. Esto sirve muy bien para ocultar / privatizar un detalle de implementación.
Es la misma idea que una clase interna o privada, pero a un nivel de encapsulación aún mayor, ya que es completamente invisible fuera de la unidad de compilación del archivo. Nada de eso aparece en el archivo de encabezado o es visible en la declaración de la clase.
fuente