Estos son idiomas muy diferentes, particularmente en esta área. Digamos que tienes una clase. En este caso, lo haremos un control de usuario, algo así como un cuadro de texto. Llámalo UIControl. Ahora queremos poner esto en otra clase. En este caso, como estamos usando una IU para nuestro ejemplo, la llamaremos la clase CleverPanel. Nuestra instancia de CleverPanel querrá saber sobre las cosas que le suceden a su instancia de UIControl por varias razones. ¿Como hacer esto?
En C #, el enfoque básico es verificar varios eventos, configurando métodos que se ejecutarán cuando se active cada evento interesante. En Java, que carece de eventos, la solución habitual es pasar un objeto con varios métodos de manejo de "eventos" a un método UIControl:
boolean stillNeedIt = ... ;
uiControl.whenSomethingHappens( new DoSomething() {
public void resized( Rectangle r ) { ... }
public boolean canICloseNow() { return !stillNeedIt; }
public void closed() { ... }
...
} );
Hasta ahora, la diferencia entre C # y Java no es profunda. Sin embargo, tenemos la interfaz DoSomething que no se necesita en C #. Además, esta interfaz puede incluir muchos métodos que no son necesarios la mayor parte del tiempo. En C #, simplemente no manejamos ese evento. En Java, creamos una clase que proporciona una implementación nula para todos los métodos de interfaz, DoSomethingAdapter. Ahora reemplazamos DoSomething con DoSomethingAdapter y no necesitamos escribir ningún método para una compilación limpia. Terminamos anulando los métodos que necesitamos para que el programa funcione correctamente. Así que terminamos necesitando una interfaz y usando herencia en Java para que coincida con lo que hicimos con los eventos en C #.
Este es un ejemplo, no una discusión exhaustiva, pero brinda los conceptos básicos de por qué hay tanta herencia en Java en comparación con C #.
Ahora, ¿por qué Java funciona de esta manera? Flexibilidad. El objeto pasado a whenSomethingHappens podría haberse pasado completamente a CleverPanel desde otro lugar. Podría ser algo que varias instancias de CleverPanel deberían pasar a sus objetos similares a UIControl para ayudar a un objeto CleverWindow en alguna parte. O el UIControl podría pasarlo a uno de sus componentes.
Además, en lugar de un adaptador, puede haber una implementación DoSomething en algún lugar que tenga miles de líneas de código detrás. Podríamos crear una nueva instancia de eso y pasarlo. Es posible que debamos anular un método. Un truco común en Java es tener una clase grande con un método como:
public class BigClass implements DoSomething {
...many long methods...
protected int getDiameter() { return 5; }
}
Luego en CleverlPanel:
uiControl.whenSomethingHappens( new BigClass() {
@Override
public int getDiameter() { return UIPanel.currentDiameter; }
} );
La plataforma Java de código abierto hace mucho de esto, lo que tiende a impulsar a los programadores a hacer más, tanto porque lo siguen como un ejemplo y simplemente para usarlo. Creo que el diseño básico del lenguaje está detrás del diseño del marco de Sun y detrás del programador de Java que usa las técnicas cuando no usa el marco.
Es realmente fácil crear una clase sobre la marcha en Java. La clase, anónima o con nombre, solo necesita ser referenciada en un pequeño bloque de código enterrado profundamente en un método. Se puede crear completamente nuevo o mediante ligeras modificaciones a una clase existente muy grande. (Y la clase existente puede ser de nivel superior en su propio archivo, o anidada en una clase de nivel superior, o definida solo dentro de un solo bloque de código). La nueva instancia de clase puede tener acceso completo a todos los datos del objeto de creación. Y la nueva instancia se puede pasar y usar en todo el programa, representando el objeto que la creó.
(Por otro lado, tenga en cuenta que un gran uso de la herencia aquí, como en otros lugares de Java, es simplemente para fines SECOS. Permite que diferentes clases reutilicen el mismo código. Tenga en cuenta también la facilidad de herencia en Java que fomenta esto. )
Nuevamente, esta no es una discusión exhaustiva; Solo estoy rascando la superficie aquí. Pero sí, hay una sorprendente diferencia en cómo se usa la herencia entre Java y C #. Son, a este respecto, idiomas muy diferentes. No es tu imaginación.