Perché le interfacce Java sono state implementate con "metodi opzionali" nell'interfaccia?

69

Durante la mia prima implementazione estendendo il framework di raccolta Java, sono rimasto piuttosto sorpreso nel vedere che l'interfaccia di raccolta contiene metodi dichiarati come facoltativi. Ci si aspetta che l'implementer lanci UnsupportedOperationExceptions se non supportato. Questo mi ha colpito immediatamente come una scarsa scelta di progettazione dell'API.

Dopo aver letto molto dell'eccellente libro di "Effective Java" di Joshua Bloch, e in seguito aver appreso che potrebbe essere responsabile di queste decisioni, non sembra gelificare i principi esposti nel libro. Penserei che dichiarare due interfacce: Collection e MutableCollection che estende Collection con i metodi "facoltativi" avrebbe portato a un codice client molto più gestibile.

C'è un eccellente sommario dei problemi qui .

C'era una buona ragione per scegliere i metodi facoltativi invece dell'implementazione delle due interfacce?

    
posta glenviewjeff 20.05.2011 - 16:18
fonte

4 risposte

28

La FAQ fornisce la risposta. In breve, hanno visto una potenziale esplosione combinatoria delle interfacce necessarie con una vista modificabile e non modificabile, solo eliminazione, sola aggiunta, lunghezza fissa, immutabile (per il threading) e così via per ogni possibile insieme di metodi di implementazione implementati.

    
risposta data 20.05.2011 - 17:09
fonte
10

A me sembra che il Interface Segregation Principle non sia stato analizzato così bene come ora; quel modo di fare le cose (cioè l'interfaccia include tutte le operazioni possibili e hai metodi "degenerati" che generano eccezioni per quelle che non ti servono) era popolare prima che SOLID e ISP diventassero lo standard de facto per il codice di qualità. / p>     

risposta data 20.05.2011 - 17:20
fonte
4

Sebbene alcune persone possano detestare i "metodi opzionali", in molti casi possono offrire semantica migliore rispetto alle interfacce altamente segregate. Tra le altre cose, consentono la possibilità che un oggetto possa acquisire abilità o caratteristiche nel corso della sua vita, o che un oggetto (specialmente un oggetto wrapper) non possa sapere quando viene costruito quale esatta abilità dovrebbe segnalare.

Anche se difficilmente chiamerò i modelli di classi di raccolta Java di buon design, suggerirei che un buon framework di collezioni dovrebbe includere alla base un gran numero di metodi facoltativi insieme a modi di chiedere una collezione sulle sue caratteristiche e abilità . Tale design consentirà di utilizzare una singola classe wrapper con una grande varietà di raccolte senza oscurare casualmente le capacità che la collezione sottostante potrebbe possedere. Se i metodi non fossero opzionali, sarebbe necessario disporre di una classe wrapper diversa per ogni combinazione di funzionalità che le raccolte potrebbero supportare, oppure in alcuni casi alcuni wrapper potrebbero essere inutilizzabili.

Ad esempio, se una raccolta supporta la scrittura di un elemento per indice, o gli elementi in coda alla fine, ma non supporta l'inserimento di elementi nel mezzo, il codice che desidera incapsularlo in un wrapper che registrerebbe tutte le azioni eseguite su di esso sarebbe serve una versione del wrapper di registrazione che fornisca l'esatta combinazione di capacità supportate, o se nessuna di queste fosse disponibile avrebbe dovuto usare un wrapper che supportava append o write-by-index ma non entrambi. Se, tuttavia, un'interfaccia di raccolta unificata forniva tutti e tre i metodi come "facoltativi", ma includeva metodi per indicare quale dei metodi facoltativi sarebbe utilizzabile, allora una singola classe wrapper potrebbe gestire raccolte che implementano qualsiasi combinazione di funzionalità. Alla domanda su quali funzionalità supporta, un wrapper potrebbe semplicemente riportare qualsiasi supporto della raccolta incapsulata.

Si noti che l'esistenza di "abilità opzionali" può in alcuni casi consentire alle raccolte aggregate di implementare determinate funzioni in modi molto più efficienti di quanto sarebbe possibile se le abilità fossero definite dall'esistenza di implementazioni. Ad esempio, supponiamo che un metodo concatenate sia stato utilizzato per formare una raccolta composita di altri due, il primo dei quali era un ArrayList con 1.000.000 di elementi e l'ultimo dei quali era una raccolta di venti elementi che poteva essere solo iterata da la partenza. Se la raccolta composita è stata richiesta per l'elemento 1.000.013 (indice 1.000.012), potrebbe chiedere all'ArrayList quanti elementi ha contenuto (cioè 1.000.000), sottrarre quella dall'indice richiesto (ottenendo 12), leggere e saltare dodici elementi dal secondo raccolta, quindi restituisce l'elemento successivo.

In una situazione del genere, anche se la raccolta composita non avrebbe un modo istantaneo di restituire un oggetto per indice, chiedere alla raccolta composita per il 1000.013 ° elemento sarebbe comunque molto più veloce della lettura di 1.000.013 elementi da esso individualmente e ignorando tutti ma l'ultimo.

    
risposta data 04.10.2014 - 23:10
fonte
-1

Lo attribuirei agli sviluppatori originali semplicemente non sapendo meglio allora. Abbiamo fatto molta strada nel design OO dal 1998 o giù di lì quando Java 2 e Collections sono stati pubblicati per la prima volta. Quello che sembra un evidente cattivo design ora non era così ovvio nei primi giorni di OOP.

Ma potrebbe essere stato fatto per prevenire il casting extra. Se fosse una seconda interfaccia dovresti lanciare le tue istanze di raccolte per chiamare quei metodi opzionali che sono anche un po 'brutti. Ora come ora, prendi immediatamente una UnsupportedOperationException e correggi il tuo codice. Ma se ci fossero due interfacce dovresti usare instanceof e lanciare ovunque. Forse hanno considerato un compromesso valido. Anche nella prima istanza di Java 2 giorni è stato gravemente disapprovato a causa delle sue prestazioni lente, potrebbero aver cercato di impedire un uso eccessivo di esso.

Naturalmente questa è tutta una speculazione selvaggia, dubito che potremmo mai rispondere con certezza a meno che una delle collezioni originali non sia architetti.

    
risposta data 20.05.2011 - 16:40
fonte

Leggi altre domande sui tag