L'ereditarietà dell'interfaccia è sempre sicura?

5

Sto leggendo "Effective Java" di Josh Bloch e c'è l'articolo 16 dove dice come usare l'ereditarietà in modo corretto e per ereditarietà si intende solo l'ereditarietà di classe, non l'implementazione di interfacce o l'estensione di interfacce da parte di altre interfacce. Non ho trovato alcuna menzione dell'ereditarietà dell'interfaccia in tutto il libro.

Questo significa che l'ereditarietà dell'interfaccia è sempre sicura? O ci sono linee guida per l'ereditarietà dell'interfaccia?

    
posta dhblah 02.12.2012 - 15:47
fonte

3 risposte

7

In generale, sì. Tuttavia, devi essere consapevole delle sorprese, alcune delle quali menziono più avanti.

Dichiarazione di non responsabilità: nessuno di questi elenchi è esaustivo.

Interfacce progettate male:

  1. con molti metodi;
  2. con metodi che non generano tipi di eccezioni sensibili, o metodi che non generano affatto (un problema in linguaggi di eccezioni controllate come Java: quando non ci si ripensa, la maggior parte delle persone di solito lancia Exception o nulla) ;
  3. con metodi che potrebbero non essere implementati, nel senso che possono lanciare UnsupportedOperationException (un'eccezione non controllata) o una sottoclasse di essa (in .NET, esiste già un NotImplementedException più esplicito); di solito visto insieme a enormi interfacce.

Cosa si può fare:

  1. Dividi le enormi interfacce;
  2. Fornire almeno una sottoclasse di Exception nello stesso spazio dei nomi dell'interfaccia;
  3. Se non puoi dividere un'interfaccia per una buona ragione, indica chiaramente quali metodi possono lanciare un UnsupportedOperationException (o NotImplementedException in .NET). Potrebbero essere tutti i metodi, ma dichiararlo chiaramente , ad esempio all'inizio della documentazione dell'interfaccia o in un piccolo paragrafo separato nella parte superiore e anche nella descrizione di ciascun metodo.

Se devi utilizzare un'interfaccia enorme che descrive quali metodi possono generare eccezioni non controllate come UnsupportedOperationException (presumo che sia un'interfaccia fuori dal tuo controllo), sii pronto a prenderle o a documentare che i tuoi metodi potrebbero lanciarle .

Un'interfaccia dovrebbe essere il più piccola possibile e la sua implementazione dovrebbe significare che è totalmente implementata. Nel mondo reale, tuttavia, non è sempre il caso, e a volte si deve passare attraverso i cerchi.

Un'implementazione di classe scadente:

  1. che implementa un'interfaccia sull'interesse di supportare solo parte del suo contratto, come uno o due dei suoi metodi, di solito non fa nulla o restituisce il non-sense per tutti gli altri metodi (a meno che non stia effettivamente implementando un osservatore);
  2. che genera UnsupportedOperationException (o NotImplementedException in .NET) in metodi in cui l'interfaccia non indica chiaramente che potrebbe essere generata;

Cosa si può fare:

  1. Avere una classe astratta che implementa la maggior parte di boilerplate e ereditarsene direttamente oppure crearne una sottoclasse e utilizzare questa nuova classe per creare un'istanza degli oggetti di delega. In effetti, molti oggetti Java Observer sono già dotati di questa funzionalità, anche se l'implementazione predefinita di tutti i suoi metodi è di non fare assolutamente nulla.
  2. Correggilo, segui il contratto. Se il codice non è tuo, prova a racchiudere tale comportamento scorretto.
risposta data 02.12.2012 - 17:14
fonte
3

Does this mean that interface inheritance is always safe? Or there are guidlines for interface inheritance?

No; si dovrebbe sempre fare attenzione a come si progetta l'interfaccia e quali contratti si applicano alle classi di implementazione. In Java sei obbligato ad implementare tutti i metodi dell'interfaccia e forse non hai davvero bisogno di tutti loro nella tua classe e non puoi nemmeno cambiare l'interfaccia.

Ad esempio, hai una grande interfaccia con numerosi metodi che chiaramente non rispettano il principio di segregazione dell'interfaccia. Se si sceglie di implementare questa interfaccia ma nella propria classe è necessario solo meno della metà dei metodi dell'interfaccia, quindi l'utilizzo dell'interfaccia ereditaria non è una buona idea.

    
risposta data 02.12.2012 - 16:02
fonte
2

Le interfacce dovrebbero essere abbastanza sparse e limitate ai metodi richiesti. Finché l'interfaccia è ben progettata è sicuro ereditarlo.

Detto questo, è possibile creare interfacce enormi con molti metodi che non sono necessari per l'interfaccia. Mentre è sicuro ereditare da loro, non è raccomandato.

La progettazione di un'interfaccia richiede un'attenta riflessione poiché una volta utilizzata può essere costosa da modificare. Cambiare l'interfaccia è difficile una volta che è stato usato. L'aggiunta di metodi o la modifica della propria firma richiede di fare lo stesso con tutti gli eredi. Rimozione dei metodi è più difficile in quanto i metodi possono includere funzionalità dell'erede, nel qual caso devono essere riqualificati o rielaborati, altrimenti dovrebbero essere rimossi.

    
risposta data 02.12.2012 - 16:13
fonte

Leggi altre domande sui tag