Queste sono lingue molto diverse, in particolare in questo settore. Diciamo che hai una lezione. In questo caso, lo renderemo un controllo utente, qualcosa come una casella di testo. Chiamalo UIControl. Ora vogliamo metterlo in un'altra classe. In questo caso, poiché utilizziamo un'interfaccia utente per il nostro esempio, la chiameremo classe CleverPanel. La nostra istanza CleverPanel vorrà conoscere le cose che accadono alla sua istanza UIControl per vari motivi. Come fare questo?
In C #, l'approccio di base consiste nel verificare la presenza di vari eventi, impostando metodi che verranno eseguiti quando viene attivato ogni evento interessante. In Java, che manca di eventi, la solita soluzione è passare un oggetto con vari metodi di gestione di "eventi" a un metodo UIControl:
boolean stillNeedIt = ... ;
uiControl.whenSomethingHappens( new DoSomething() {
public void resized( Rectangle r ) { ... }
public boolean canICloseNow() { return !stillNeedIt; }
public void closed() { ... }
...
} );
Finora, la differenza tra C # e Java non è profonda. Tuttavia, abbiamo l'interfaccia DoSomething che non è necessaria in C #. Inoltre, questa interfaccia potrebbe includere molti metodi che non sono necessari per la maggior parte del tempo. In C #, non gestiamo quell'evento. In Java, creiamo una classe che fornisce un'implementazione nulla per tutti i metodi di interfaccia, DoSomethingAdapter. Ora sostituiamo DoSomething con DoSomethingAdapter e non abbiamo bisogno di scrivere alcun metodo per una compilazione pulita. Finiamo solo per ignorare i metodi di cui abbiamo bisogno per far funzionare correttamente il programma. Quindi abbiamo bisogno di un'interfaccia e di usare l'ereditarietà in Java per abbinare ciò che abbiamo fatto con gli eventi in C #.
Questo è un esempio, non una discussione completa, ma fornisce le basi del perché c'è così tanta eredità in Java rispetto a C #.
Ora, perché Java funziona in questo modo? Flessibilità. L'oggetto è passato a quando SomethingHappens avrebbe potuto essere passato a CleverPanel da qualche altra parte completamente. Potrebbe essere qualcosa che diverse istanze di CleverPanel dovrebbero passare ai loro oggetti simili a UIControl per aiutare un oggetto CleverWindow da qualche parte. Oppure UIControl potrebbe consegnarlo a uno dei suoi componenti.
Inoltre, invece di un adattatore potrebbe esserci un'implementazione DoSomething da qualche parte che ha migliaia di righe di codice dietro di esso. Potremmo creare una nuova istanza di quello e passarlo. Potrebbe essere necessario sostituire un metodo. Un trucco comune in Java è avere una grande classe con un metodo come:
public class BigClass implements DoSomething {
...many long methods...
protected int getDiameter() { return 5; }
}
Quindi in CleverlPanel:
uiControl.whenSomethingHappens( new BigClass() {
@Override
public int getDiameter() { return UIPanel.currentDiameter; }
} );
La piattaforma Java open source fa molto di questo, che tende a spingere i programmatori a fare di più, sia perché la seguono come esempio sia semplicemente per usarla. Penso che il design di base del linguaggio sia alla base della progettazione del framework Sun e dei programmatori Java che usano le tecniche quando non usano il framework.
È davvero facile creare una classe al volo in Java. La classe, anonima o denominata, deve essere referenziata solo in un piccolo blocco di codice sepolto in profondità in un metodo. Può essere creato completamente nuovo o con lievi modifiche a una classe esistente molto ampia. (E la classe esistente può essere di livello superiore nel proprio file o nidificata in una classe di livello superiore o definita solo all'interno di un singolo blocco di codice). La nuova istanza della classe può avere pieno accesso a tutti i dati dell'oggetto di creazione. E la nuova istanza può essere passata e utilizzata in tutto il programma, rappresentando l'oggetto che l'ha creata.
(A parte, nota che un grande uso dell'eredità qui - come in altri luoghi in Java - è semplicemente per scopi SECCHI. Permette a classi diverse di riutilizzare lo stesso codice. Nota anche la facilità di eredità in Java che lo incoraggia. )
Ancora una volta, questa non è una discussione esauriente; Sto solo grattando la superficie qui. Sì, c'è una differenza sorprendente nel modo in cui l'ereditarietà viene utilizzata tra Java e C #. Sono, a questo proposito, lingue molto diverse. Non è la tua immaginazione.