java - internas - crear un objeto de una clase dentro de otra clase
¿Cuál es la ventaja de tener clases internas estáticas públicas de una interfaz/clase? (7)
Creo que esto se basa en la agregación, tal vez tampoco valen la pena para crear una clase de nivel superior. A veces hago esto si algo es demasiado pequeño para crear un paquete (para separarlos de los demás), pero las clases correspondientes solo deben usarse dentro del contexto de la clase de nivel superior. En mi opinión, esta es una decisión de diseño.
El patrón de decorador puede ser un buen ejemplo, se pueden aplicar en la clase de nivel superior, pero tal vez sean tan simples que no valen la pena para ser también de alto nivel. Puede mostrar fácilmente la propiedad utilizándolas como clases internas.
Eso no es tan visible a primera vista con los paquetes. Usted ve directamente la clase / interfaz dependiente.
Además, es posible acceder a los campos privados de una clase, esto podría ser útil y más preciso que el alcance privado del paquete.
He notado el siguiente patrón de código mientras navego por algunas fuentes de las bibliotecas de terceros de mi proyecto:
public interface MyInterface {
public static class MyClass1 implements MyInterface { ... }
public static class MyClass2 implements MyInterface { ... }
public static class MyClass3 implements MyInterface { ... }
}
O este:
public class MyBaseClass {
public static class MyClass1 extends MyBaseClass { ... }
public static class MyClass2 extends MyBaseClass { ... }
public static class MyClass3 extends MyBaseClass { ... }
}
Ejemplos de vida real:
- SwingX:
org.jdesktop.swingx.decorator.HighlightPredicate
( Source ) - Sustancia:
org.pushingpixels.substance.api.renderers.SubstanceDefaultTableCellRenderer
( Source )
¿Cuál es la ventaja de tener una estructura de código como esta?
Mi primer pensamiento fue "agregación", pero lo mismo podría lograrse usando paquetes antiguos simples. Entonces, ¿cuándo / por qué es mejor utilizar clases internas públicas en lugar de un paquete?
Creo que la razón de la clase interna estática pública es una herramienta o utilidad adicional para la clase "base".
Cuando le pregunté a mi profesor sobre esto hace muchos años, respondió que de esta manera puedes exponer una interfaz totalmente diferente para el mismo objeto. Supongamos que tiene
public class MyBaseClass {
public static class MyClass1 {
public int myClassMethod1() {...}
public int myClassMethod2() {...}
}
...
public void myBaseMethod1() {...}
public void myBaseMethod2() {...}
}
Debido a que las instancias de MyClass1
tienen acceso a las MyBaseClass
internas de MyBaseClass
, puede exponer el mismo comportamiento interno como una instancia de MyClass1
o como una instancia de MyBaseClass
según lo necesite, incluso si los métodos definidos en ambas clases son totalmente diferentes.
Nunca tuve que usar eso, pero es realmente interesante.
Si lo hace de esta manera puede ahorrarle algunos archivos de código fuente adicionales y le permite darle a la clase un buen nombre jerárquico, es decir, org.foo.bar.XY.Default
lugar de org.foo.bar.DefaultXY
Un uso en el que puedo pensar es proporcionar implementaciones ya hechas de la interfaz, públicamente disponibles para todos, pero aún atadas conceptualmente a la interfaz madre.
Esto solo tiene sentido si la interfaz es simple (por lo tanto, las clases de implementación interna son pequeñas), no hay demasiadas y la mayoría de los clientes de interfaz realmente las necesitan. De lo contrario, complican el archivo fuente, lo que dificulta su comprensión.
Una interfaz interna tiene que ser estática para acceder. La interfaz no está asociada con instancias de la clase, sino con la clase en sí misma, por lo que se accedería con Foo.Bar
, como tal.
En lo que respecta a las clases y sus clases internas (no se aplica a las interfaces), una diferencia es que las clases internas pueden usar miembros privados de la clase externa, lo que no es el caso si fueran hermanos (nivel superior separado) clases).
Ejemplo:
public class MyBaseClass {
private static String staticField = "outer";
public static class MyClass1 extends MyBaseClass {
public MyClass1() {
MyBaseClass.staticField = "inner1";
}
}
}
Esto no funcionará si movió el MyClass
fuera de la clase externa.