Come implementare solo una parte di un'interfaccia

13

Quando si sviluppa in OOP, a volte un'interfaccia / contratto è data da una libreria che non è possibile modificare. Chiamiamo questa interfaccia J.

Ora hai un oggetto di classe A che consuma oggetti che implementa questa interfaccia. Dentro A è necessaria solo una piccola parte delle definizioni dell'interfaccia. Alcune delle classi oggetto sono create da me durante il progetto (chiamiamone uno di loro tipo D), quindi c'è un sovraccarico nell'implementazione di tutto all'interno dell'interfaccia J.

Voglio implementare un sottoinsieme della funzionalità nell'interfaccia J, ma le mie soluzioni finora non mi soddisfano:

  • implementare ogni aspetto di J e lanciare "notImplementedExceptions" disinforma l'utente dei miei oggetti: sembrerebbe che i miei oggetti di tipo D siano conformi all'interfaccia J, ma non lo fanno - e altri consumatori dei miei oggetti (che accettano oggetti che implementano l'interfaccia J) non possono fare affidamento sull'integrità dei miei oggetti.
  • L'implementazione di un'interfaccia appena definita mi impedisce di utilizzare oggetti che implementano solo l'interfaccia J, sebbene l'interfaccia J sia completamente compatibile con la mia interfaccia.
  • Lasciare che i miei oggetti personalizzati implementino l'interfaccia J creerebbe un sovraccarico significativo, perché non hanno bisogno di tutte queste funzionalità.

Quando sono stato in grado di modificare l'interfaccia J, vorrei creare una "superinterfaccia" K che avesse questo sottoinsieme della funzionalità dell'interfaccia J, e rendere l'interfaccia J ereditata dall'interfaccia K. Ma non posso modificare l'interfaccia J.

Che cos'è una soluzione orientata agli oggetti a questo problema? La soluzione migliore è ancora implementando l'interfaccia "giusta" J? O ci sono OOP-modi per "superclassare" un'interfaccia senza alterarla?

    
posta vstrien 01.06.2011 - 10:34
fonte

6 risposte

8

se non controlli l'interfaccia J, sei bloccato.

puoi, per chiarezza, implementare la tua interfaccia subJ e interfaccia J, e usare subJ nel tuo codice per chiarire che i metodi extra nell'interfaccia J non sono richiesti, ma io non Penso che ti guadagni davvero molto

se possibile, implementa l'intera interfaccia J completamente

se possibile, contatta il proprietario dell'interfaccia J e chiedigli di modificarlo per adattarlo meglio ai tuoi scopi

    
risposta data 01.06.2011 - 11:14
fonte
25

L'intero punto di implementazione di un'interfaccia è di fornire un contratto aziendale tra il chiamante e il chiamato che non cambia mai mentre i dettagli di implementazione possono variare.

Implementando l'interfaccia J stai dicendo al mondo esterno cosa puoi fare.

Se non hai bisogno di metà di ciò che fa J, allora l'interfaccia dovrebbe essere veramente suddivisa in quanto non è così piccola come potrebbe essere, oppure devi lanciare NotImplementedException sui metodi e le proprietà che non ti servono . Tuttavia, questa non è la soluzione migliore in quanto confonde le aspettative delle persone su ciò che il tuo codice può fare.

    
risposta data 01.06.2011 - 11:18
fonte
4

Se la tua classe consumer A non richiede tutta l'interfaccia J, allora ti suggerirei di creare una nuova interfaccia (chiamala K), che descriva esaustivamente tutto ciò che richiede.

Questo fornisce un chiaro segnale a chiunque usi la classe A su quale sia la loro parte del contratto. In tal modo migliorare le possibilità di riutilizzo. Se qualcuno ha bisogno di fornire un oggetto che implementa un'interfaccia ampia e complessa, per fare qualcosa di relativamente semplice, probabilmente finirà per scrivere qualunque classe A faccia da sé.

Per consentire alla classe A di consumare oggetti che implementano solo l'interfaccia J, è possibile fornire una classe wrapper che implementa l'interfaccia K e passa qualsiasi chiamata appropriata a un membro di interfaccia J.

    
risposta data 01.06.2011 - 12:04
fonte
3

Anche se sono d'accordo con le risposte esistenti che dicono che è necessario implementare completamente J (con eccezioni per i metodi non implementati) o non farlo affatto, una possibile soluzione è la seguente:

  • Crea un'interfaccia più piccola K che è un sottoinsieme di J e implementa i metodi richiesti.
  • Crea un wrapper per A che accetta oggetti che implementano J e K.
  • Nel caso di un passato in J, è sufficiente inserirlo nell'istanza di A.
  • Nel caso di un passaggio in K, istanziare un'implementazione anonima di J, collegare solo i metodi da K a J che ci sono. Passa il risultato all'istanza di A.

Si noti che questa è una soluzione piuttosto brutta, dal momento che richiede un wrapper che accetta più cose che sono essenzialmente la stessa cosa. Ma realizza quanto segue:

  • Nessuna modifica a J o A
  • Nessuna implementazione "esposta" di J incompleta.

Se il tuo linguaggio OO non consente l'istanza di un'interfaccia anonima, puoi creare un'implementazione fittizia dell'interfaccia e creare un'istanza di questo.

    
risposta data 01.06.2011 - 11:27
fonte
1

Quanto tempo impiegherebbe a implementare l'intera interfaccia?

Se ti ci vorrà molto tempo, questo indica un problema di progettazione, e ti consiglierei (come ha fatto Steven A. prima di me) di contattare il proprietario e vedere se può essere modificato in futuro.

Usi l'interfaccia nel tuo codice, indipendentemente dalla libreria dell'interfaccia?

Come suggerito da Steven A., puoi usare la tua interfaccia come vorresti vederla nel tuo codice. Questo almeno mantiene pulito il codice inhouse. Puoi anche inviarlo al proprietario come l'interfaccia che ti aspetteresti di trovare. Forse è d'accordo con te, o forse può spiegarti perché l'interfaccia non deve essere divisa.

La tua implementazione avrebbe mai avuto bisogno dei membri inutilizzati dell'interfaccia?

Nel caso in cui ci si possa aspettare che non vengano mai chiamati perché "non sono supportati", preferisco usare NotSupportedException . Ciò fornisce una chiara indicazione che non supporterai mai questa interfaccia, piuttosto che non l'hai implementata.

    
risposta data 01.06.2011 - 11:49
fonte
0

Implementa ciò che ti serve e genera un'eccezione NoImplementedException sugli altri.

Questa è una questione di utilizzo. Se non utilizzi l'interfaccia o sai che il tuo codice non utilizzerà l'interfaccia, non investire tempo in questo, poiché non è necessario investire tempo in codice ridondante.

Lavora per il compito da svolgere e mantieni una buona traccia per gli altri da seguire se vogliono utilizzare l'interfaccia.

Molte interfacce in Java non sono completamente implementate.

Questo è l'aproach delle Apache per le cose: link

    
risposta data 01.06.2011 - 11:14
fonte

Leggi altre domande sui tag