Sono lingue molto diverse, in particolare in quest'area. 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, dal momento che utilizziamo un'interfaccia utente per il nostro esempio, la chiameremo classe CleverPanel. La nostra istanza di CleverPanel vorrà conoscere le cose che accadono nella sua istanza di UIControl per vari motivi. Come si fa?
In C #, l'approccio di base è controllare vari eventi, impostando i metodi che verranno eseguiti
quando viene attivato ogni evento interessante. In Java, a cui mancano gli eventi, la solita soluzione è passare un oggetto con vari metodi di gestione "evento" 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 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 per ignorare i metodi di cui abbiamo bisogno per far sì che il programma funzioni correttamente. Quindi alla fine abbiamo bisogno di un'interfaccia e che utilizzi l'ereditarietà in Java per corrispondere a 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 ereditarietà in Java rispetto a C #.
Ora, perché Java funziona in questo modo? Flessibilità. L'oggetto passato a whenSomethingHappens 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. O l'UIControl potrebbe consegnarlo a uno dei suoi componenti.
Inoltre, al posto di un adattatore potrebbe esserci un'implementazione DoSomething da qualche parte che contiene migliaia di linee di codice. Potremmo creare una nuova istanza di che e passarla. Potremmo aver bisogno di sovrascrivere un metodo. Un trucco comune in Java è di avere una classe grande 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, il che tende a spingere i programmatori a fare di più - sia perché lo seguono come un esempio che semplicemente per usarlo. Penso che il design di base del linguaggio sia alla base del framework di Sun e dietro il programmatore Java che usa le tecniche quando non usa 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 piccole modifiche a una classe molto grande ed esistente. (E la classe esistente può essere di primo livello nel proprio file o nidificata in una classe di primo livello o definita solo all'interno di un singolo blocco di codice). La nuova istanza di classe può avere accesso completo 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 lo ha creato.
(Come nota a parte, si noti che un grande uso dell'eredità qui - come in altri posti in Java - è semplicemente a scopi DRY. Consente a diverse classi di riutilizzare lo stesso codice. Nota anche la facilità di ereditarietà in Java che lo incoraggia.)
Ancora una volta, questa non è una discussione completa; Sto solo grattando la superficie qui. Ma sì, c'è una sorprendente differenza nel modo in cui viene utilizzata l'ereditarietà tra Java e C #. Sono, sotto questo aspetto, linguaggi molto diversi. Non è la tua immaginazione.