¿Por qué los marcos de Windows Forms / Swing favorecen la herencia en lugar de la Composición?

12

Hoy, un profesor mío comentó que le pareció extraño que, si bien la filosofía de SWT es hacer sus propios controles por composición, Swing parece favorecer la herencia.

Casi no tengo contacto con ambos frameworks, pero por lo que recuerdo en los formularios Windows Forms de C #, uno generalmente extiende los controles, al igual que Swing.

Siendo que, en general, las personas tienden a preferir la composición sobre la herencia, ¿por qué la gente de Swing / Windows Forms no prefería la composición en lugar de la herencia?

elysium devorado
fuente
2
¡Mucho ha cambiado en los 15-20 años que esas API han existido! Los motores de renderizado no tenían pegamento XML mágico para unir objetos de pantalla con instancias de ninguna clase concreta arbitraria "en el día";)
1
La mayoría del código Swing que veo usa extensión por composición. No estoy seguro de dónde obtiene su profesor sus datos.
Yo mismo he visto muchos cambios en la red con herencia en lugar de composición, aunque en su mayoría tutoriales. ¡pero las formas de Windows realmente se usan casi exclusivamente por herencia!
devorado elysium

Respuestas:

7

JComponentexpone mucha funcionalidad . Si JComponenthubiera una interfaz y los componentes se implementaran con composición, los componentes simples tendrían que tener docenas de envoltorios de métodos triviales, p. Ej.

class MyComponent implements JComponent {
    JPanel panel;
    public boolean contains(int x, int y) {
        return panel.contains(x, y);
    }
    ...
}

También hay una razón de eficiencia para preferir la herencia a la composición: la anulación no cuesta nada (suponiendo que no hay superllamadas), mientras que la composición cuesta un extra INVOKEVIRTUAL. No sé si esto influyó en el diseño de Swing, pero es una gran preocupación para las clases de colección.

Daniel Lubarov
fuente
2

Swing Framework está diseñado de acuerdo con el patrón de diseño compuesto. De acuerdo con que hay mucha herencia allí, pero generalmente compondría sus propios formularios utilizando la composición. Es decir, un formulario es una composición de contenedores y controles de nivel intermedio.

Vincent Ramdhanie
fuente
"Es decir, un formulario es una composición de contenedores y controles de nivel intermedio". Seguro. Pero lo que veo generalmente es que cuando las personas quieren crear su propia ventana (o como se llame en Swing), heredarán de una clase de ventana en lugar de usar composición.
Devorado elysium
@ elysium devorado Eso es cierto. Pero para crear la forma usarían composición. Por lo tanto, es un poco de herencia y mucha composición.
@devoured, creo que es un caso de personas que no se dan cuenta de que el tutorial que usan no sigue las mejores prácticas porque favorece la brevedad.
Peter Taylor
1

Con Java, es mucho más fácil terminar usando la herencia solo porque todo es virtual. ¿Necesita arreglar una "característica" en JTable / JFrame? Extiéndalo, anule los métodos problemáticos y luego use su Tabla / Marco en todas partes.

Creo que con cosas como WPF, donde el enlace de datos es una característica principal del diseño, hace que sea mucho más fácil hacer la composición en lugar de la herencia.

John Gardner
fuente
¿Qué quieres decir con "todo es virtual "?
Jonas
en java, cada método es implícitamente virtual (puede ser reemplazado). En C #, debe declarar explícitamente un método como virtual, y para anularlo, lo declara explícitamente como un override. En java, puede anular cualquier cosa que pueda ver, y puede aumentar su visibilidad en una subclase (¡puede hacer públicos los métodos protegidos en una subclase!)
John Gardner
Tenga en cuenta que no puede anular un finalmétodo en Java, incluso si la clase base en sí no lo es final.
perp
eso es cierto @perp. pero en java tienes que salir de tu camino (agregando final) para evitar virtual. C # es lo contrario, tienes que salir de tu camino para ser virtual. Y un porcentaje muy pequeño del tiempo de ejecución estándar de Java se marca como final.
John Gardner
1

En Effective Java , Item 17, Bloch menciona que una clase diseñada para la herencia "debe documentar su auto uso de métodos reemplazables". Un sello distintivo de esto es la frase esta implementación . Lo verás en clases como JTabley JInternalFrame. Es una medida de herencia por diseño en Swing.

trashgod
fuente
-2

De C # 3.5, tenemos un concepto llamado como métodos de extensión que permite el concepto de composición que de herencia.

En este proceso, implementamos una funcionalidad extendida a una clase existente simplemente agregando una clase de extensión que representa la nueva característica a la clase existente.

Puede consultar aquí para más detalles.

Saravanan
fuente
No veo la relevancia para crear nuevas clases de control de WinForms. ¿Podrías dar más detalles?
Peter Taylor
@ Peter: Esto no está relacionado solo con las clases de formularios de Windows. Esto puede ser aplicable desde nuestro código también. Puede extender cualquiera de las clases existentes simplemente agregando una clase estática y luego agregando un nuevo método con el primer argumento como este para que el objeto base pueda vincularse. Después de compilar el código, obtiene el método recién agregado como un método de la clase base en sí. Esto es lo que dice la composición. Espero tener razón ..
Saravanan
1
Sé qué son los métodos de extensión, y a veces son bastante útiles, pero esta pregunta trata sobre diferentes enfoques para crear nuevas clases.
Peter Taylor
@ Peter: Entonces solo puedo señalar el uso de clases parciales solamente, aparte de eso, a mi entender, C # no tiene ninguna otra característica notable. Si conoce alguno, por favor hágamelo saber.
Saravanan