2011-05-05 12 views
6

que se utilizó para la subclasificación de las ventanas-clases en otro entorno de programación, pero en los tutoriales de Java que suelo ver algo así como¿Debería subclasificar JFrame/JPanel o no?

JPanel p = new JPanel(); 
p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS)); 

p.add(aComponent); 
p.add(anotherComponent); 

¿Cuáles son las convenciones en Java con respecto a la subclasificación de clases de contenedor superior?

+1

Esta pregunta es similar a la que deben utilizar las clases anónimas o debería nómbrelos -> no hay correcto o incorrecto. – rurouni

Respuesta

6

Usar el mismo principio que lo haría para todas las clases de Java. Si está modificando o ampliando el comportamiento o la funcionalidad, entonces por supuesto, extienda JPanel o JFrame. El truco es pensar detenidamente y decidir si realmente estás agregando algo. En la mayoría de los casos cuando veo personas que extienden JFrame es innecesario e incorrecto;

public class MyFrame extends JFrame { 
    public static void main(String[] args) { 
    new MyFrame().setVisible(true); 
    } 
} 

por qué molestarse extendiéndose JFrame? ¡No has agregado nada! La composición es una opción mucho mejor.

Extendiendo JPanel es un poco diferente. JPanel es una idea bastante abstracta, es solo un contenedor genérico para otros componentes. En mi humilde opinión, es válido crear la subclase JPanel para crear un panel más concreto, y luego usarlo en su aplicación. Promueve OOP y encapsulación.

Por ejemplo, decir que su interfaz gráfica de usuario tenía 2 zonas principales de visualización; uno con algunos botones/controles/entradas y otro que muestra la salida (por ejemplo, en un área de texto). Es perfectamente aceptable la subclase JPanel para crear un ControlPanel que contenga los botones/controles/entradas. Esto mueve todo el código a un bonito y ordenado módulo, limpiando tu clase que contiene y maneja el principal JFrame.

+0

A menudo, cuando las personas tienen una clase principal de aplicación con atributos de datos y la lógica de negocio, etc, que se extiende JFrame verlos puramente con el fin de dar a su aplicación una interfaz gráfica de usuario. IMO esto es incorrecto, porque no es un * is-a *, es un * has-a *! Como dijiste, composición el enfoque correcto. Sin embargo, si * necesita * para extender JFrame/JPanel a ** agregar alguna funcionalidad relacionada con la interfaz de usuario **, no use esto como excusa para poner todo en una clase. Debería darle a su clase de aplicación una instancia de su JFrame extendido, y no comenzar a almacenar datos/lógica de negocios en lo que debería ser una clase puramente de UI. Solo mi $ 0.02. –

3

No existe una regla para esto, depende de cómo piense sobre su objeto. Es posible que tengas un JPanel que tenga un diseño y un comportamiento específicos, por lo que, por ejemplo, un Panel de VideoViewer. Pero incluso este Panel de VideoViewer puede contener un JPanel que solo está allí para organizar algunos Botones, por lo que no le da un nombre explícito y simplemente lo usa como JPanel.

1

Una buena práctica conocida es evitar la subclasificación de contenedores de nivel superior (JFrame, JDialog, JInternalFrame).

En cuanto JPanel, varias prácticas están en uso:

  • subclase para todas las vistas (a continuación, añadir todos los componentes dentro del constructor de la subclase )
  • crear un ViewBuilder (para cada especie of view) que agrega dinámicamente componentes a un "estándar" JPanel

Generalmente utilizo la primera opción, que me parece más lógica, pero también uso la segunda vía, con cierto nivel de adaptación: mi generador de vistas realmente crea y almacena (como campos) todos los componentes pero agrega a un panel existente (pasado como argumento).

Por ejemplo, lo uso para reutilizar conjuntos de componentes: p. Tengo una clase AddressView que funciona de esa manera y lo añado dos veces a un ContactView que JPanel subclases, una vez para domicilio, una vez dirección de la oficina .

Se puede decir que también pude establecer la subclase JPanel para y luego agregar 2 instancias a mi panel ContactView. La razón por la que no hago eso es porque Swing LayoutManager s no admite la alineación de componentes en diferentes paneles, por lo que el panel ContactView resultante no es visualmente agradable en este caso.

1

Mi regla general: Antes de usar la herencia, considere si la composición tiene más sentido.

Motivo: subclases por lo general significa una mayor complejidad y conectividad, es decir, más difíciles de cambiar, mantener y escala sin cometer errores.

una forma mucho más completa y concreta answer from Tim Boudreau del sol:

problemas comunes a la utilización de la herencia como la veo son:

  • actos inocentes pueden tener resultados inesperados - El El ejemplo clásico de esto son las llamadas a métodos invalidables del constructor de la superclase , antes de que los campos de la instancia de subclases hayan sido inicializados. En un mundo perfecto, nadie haría eso nunca. Esto es no es un mundo perfecto.
  • Ofrece tentaciones perversas a los subclasistas para hacer suposiciones sobre el orden de las llamadas a métodos y tales - tales suposiciones tienden a no ser estables si la superclase puede evolucionar con el tiempo. Consulte también my toaster and coffee pot analogy.
  • Las clases se vuelven más pesadas - no necesariamente sabes qué trabajo está haciendo tu superclase en su constructor, o cuánta memoria usa .Por lo tanto la construcción de algunos de los posibles inocentes objeto ligero puede ser mucho más caro de lo que cree, y esto puede cambiar con el tiempo si la superclase evoluciona
  • Se alienta una explosión de subclases. La carga de clases cuesta tiempo, más clases cuestan memoria. Esto puede ser un problema inexistente hasta que esté se trata de una aplicación en la escala de NetBeans, pero allí, tuvimos reales problemas con, por ejemplo, los menús de ser lento debido a que la primera pantalla de un menú activa la carga masiva de clases . Hemos fijado esto mediante el movimiento de más sintaxis declarativa y otras técnicas, pero que el tiempo costo para arreglar también.
  • Hace más difícil cambiar las cosas más tarde - si ha hecho una clase pública, el intercambio de la superclase va a romper las subclases - es una opción que, una vez que haya hecho público el código, está casado a. Así que si usted no está alterando la funcionalidad real a sus superclase, se obtiene mucha más libertad para cambiar las cosas más adelante, si uso, en lugar de ampliar lo que necesita. Tomemos, por ejemplo, subclases de JPanel: esto suele ser incorrecto; y si la subclase es pública , nunca tendrá la oportunidad de volver a tomar esa decisión. Si se accede como JComponent getThePanel(), aún puede hacerlo (pista: exponer modelos para los componentes dentro como su API).
  • Las jerarquías de objetos no se escalan (o hacer que escalen después es mucho más difícil que planificar con anticipación) - este es el problema clásico de "demasiadas capas" . Voy a entrar en esto a continuación, y cómo el patrón AskTheOracle puede resolverlo (aunque puede ofender a los puristas de OOP).

...

Mi opinión sobre qué hacer, si no permiten la herencia, que es posible que tomar con un grano de sal es:

  • Expose ningún campo, siempre , excepto constantes
  • métodos será, o bien abstracta o final de
  • Call no hay métodos desde el constructor de la superclase

...

todo esto se aplica menos a proyectos pequeños que grandes, y menos a clases privadas que las públicas

Cuestiones relacionadas