La composizione sull'ereditarietà è una vecchia tendenza o addirittura uno stato dell'arte nella programmazione orientata agli oggetti. Sarebbe ancora più facile da usare in Java, se esistesse un supporto linguistico per la delega. I nostri IDE, come eclipse, consentono una facile generazione di metodi di delega, ma il risultato è un terribile disordine di codice. Mi piacerebbe piuttosto vedere qualcosa di simile
class ExtendedList<T> implements List<T> {
List<T> values = new ArrayList<T>();
delegate values.*;
...
}
dove delegate
è una nuova parola chiave per la lingua che non è altro che una scorciatoia per ciò che l'IDE fa esplicitamente quando gli chiedi di delegare a tutti i metodi del campo values
.
Potrei andare avanti per confrontare questo con l'ereditarietà e come il risultato potrebbe essere più o meno lo stesso, date le interfacce, ma più esplicito e permettendo una "eredità multipla" a grana fine, esplicita, ma questa discussione deve essere già avvenuta qualche volta nel passato in alcune mailing list Java. Tuttavia, sono riuscito a trovare solo link di 15 anni, ad esempio su beust.com e citeseer che descrive idee molto simili a quelle che ho in mente.
Penso che questo sia (a) veramente utile e (b) banale da implementare in un compilatore, tuttavia in 15 anni non è apparso nulla in Java.
Quindi la mia domanda è: cosa mi manca? C'è un ostacolo importante nell'attuazione di ciò di cui non sono a conoscenza?
Per inciso: mi piacerebbe avere dei buoni consigli su, ad esempio, Java / JCP / JSR / qualunque sia stato discusso. Non sono riuscito a trovarne.
Come richiesto, fammi provare un altro esempio:
class FileWithMetas extends OutputStream implements Map<String,String> {
final OutputStream out;
delegate out.*; // takes care of "extend OutputStream"
final Map<String,String> metas = new HashMap<>();
delegate metas.*; // takes care of "implements Map"
public FileWithMetas(...) {
this.out = new FileOutputStream(...);
}
@Override //explicitly re-implement the delegated out.close()
public void close() {
//serialize the metas, for example
out.close(); // with classic inheritance this would be super.close()
}
}
Alla fine sembrerà molto più un'eredità multipla, ma come accennato: la delega è solo la sintassi dello zucchero che sostituisce i metodi di delega generati dall'IDE e, fatta eccezione per i messaggi di errore leggermente diversi, il compilatore dovrebbe comportarsi esattamente così. In effetti, penso che questo potrebbe sostituire completamente l'ereditarietà (non che io lo stia chiedendo) - dato che manteniamo le interfacce, ovviamente, che ci permettono di separare i tipi dall'implementazione.