Java senza ereditarietà dell'implementazione

7

In un video recente su Java, Joshua Bloch afferma in 4 minuti e 20 secondi nel video:

And then there's inheritance, and that was a marketing necessity. You know, we can argue whether you really need implementation inheritance or not.

Quindi mi sono chiesto: come sarebbe l'aspetto di Java senza l'ereditarietà dell'implementazione? Ad esempio, in che modo equals , hashCode e toString funzionano? Invece, Java avrebbe avuto bisogno di qualcosa come mixin?

    
posta fredoverflow 09.08.2011 - 21:23
fonte

5 risposte

4

Con un'API pubblica adatta posso vedere qualcosa come i metodi di estensione .net che servono molto allo stesso scopo.

public static boolean equals(this Object that, Object other) {
  return (this == other);
}

Ci vorrebbe un cambio di lingua, ovviamente, ma potresti ottenere un sacco di riutilizzo con una sintassi molto simile a ciò che abbiamo oggi.

    
risposta data 09.08.2011 - 21:46
fonte
4

Per il tuo esempio particolare, che ne dici di usare semplicemente le funzioni prendendo invece l'oggetto come argomento?

toString(Object obj)
hash(Object obj)
equals(Object a, Object b)

Penso che le persone tendano ad essere piuttosto estremiste in ciò che "pensano" sia terrificante o catastrofico.

Siamo obiettivi. L'ereditarietà è utile in molti casi. Non è una "necessità", ma è piuttosto utile in alcuni casi. Tuttavia, sì, tende ad essere sovrautilizzato / sovraspromosso e talvolta introduce complessità dove non dovrebbe.

Possiamo vivere senza ereditarietà nei linguaggi di programmazione tradizionali? Non proprio. Sono una costruzione essenziale e utile. Fare senza di loro sarebbe un rompicoglo.

Possiamo trovare altri meccanismi che sono migliori dell'ereditarietà? Certamente. L'ereditarietà singola è molto limitata, l'ereditarietà multipla è una lama a due lati. Ma l'eredità stessa potrebbe non essere la strada migliore del tutto. Un modo sono i tratti come in Scala, le classi come in Haskell (niente a che fare con le normali classi) e molti altri meccanismi.

Tuttavia, si potrebbe andare anche oltre e si chiede se gli "oggetti" sono la strada da percorrere nel nostro mondo moderno. Forse qualcosa con tipi di dati algebrici e agenti asincroni si adatterebbe meglio alle sfide del parallelismo massiccio e dell'espressività nei linguaggi di programmazione. (Sì, lo so, questo suona come un mumbo-jumbo accademico, ma dietro c'è qualcosa di molto concreto.)

    
risposta data 09.08.2011 - 22:07
fonte
3

Google's go è un esempio di linguaggio che elimina l'ereditarietà dell'implementazione mentre è OOP, supporta il polimorfismo e fa riferimento alla tua domanda, interfacce componibili.

Penso che il problema più grande con l'ereditarietà dell'implementazione sia il seguente: Considera una classe Stack che potrebbe essere implementata usando una classe Queue. Potresti farlo in due modi, un modo sarebbe quello di ricavare la pila dalla coda e aggiungere i metodi push () e pop (). L'altro sarebbe quello di incorporare un'istanza di coda all'interno di uno stack e utilizzarlo per implementare push () e pop (). In generale, quest'ultimo è preferito, quindi il "contratto" di classe non viene mai confuso. D'altro canto, incorporare un'istanza all'interno di un'altra sarebbe un buon modo per ottenere il riutilizzo del codice senza rovinare il contatto della classe.

Il contratto di classe d'altra parte (la sua interfaccia) dovrebbe essere componibile o soggetto ad ereditarietà.

    
risposta data 10.08.2011 - 06:16
fonte
0

Non riesco a vedere di essere un purista del linguaggio che ti sbarazzi dell'eredità singola, quindi risolvi il problema con i mix-in che consentono l'ereditarietà multipla dell'implementazione.

Buon punto a proposito di equals, hashCode e toString, la mia ipotesi è che entrambi avrebbero il default del compilatore nell'implementazione altrimenti gli strumenti di ognuno avrebbero (un po 'sconfiggendo le motivazioni puriste).

Poiché le sottoclassi diventerebbero fondamentalmente dei decoratori, immagino che il supporto degli strumenti per i decoratori diverrebbe un'enorme priorità. Se alla fine della giornata le cose diventassero più pure o le persone farebbero solo tagli e incisioni, l'ereditarietà non potrà mai essere conosciuta.

    
risposta data 09.08.2011 - 22:07
fonte
0

Il polimorfismo è la fine, l'eredità è un mezzo. È abbastanza facile da capire e penso che sia abbastanza utile. In Java, sono un grande fan del modello di metodo del modello che generalmente evita la necessità di invocare super . Ogni volta che ho invocato super in Java, mi sono sentito un po 'sporco per qualche motivo.

    
risposta data 09.08.2011 - 22:41
fonte