È ragionevole che un'interfaccia specifichi che le sue implementazioni dovrebbero essere immutabili?

5

Diciamo che ho un'interfaccia A . Le istanze di classi che implementano questa interfaccia verranno passate ad un algoritmo che si basa su queste istanze che sono immutabili. Ad esempio, invocherà A.execute(command) in modo ricorsivo, un numero di volte che dipende dai parametri dati. Se execute() cambia lo stato dell'istanza, l'algoritmo non funzionerà come previsto.

Dato che l'immutabilità non può essere applicata (almeno in Java) dall'interfaccia, sto pensando di scriverla nella documentazione della classe, come un contratto.

È ragionevole o sto imponendo un dettaglio di implementazione?

    
posta garci560 29.08.2017 - 00:58
fonte

3 risposte

13

Sì, questo è assolutamente ragionevole.

Esamina l'API Stream , ad esempio, molti vincoli sono espressi come JavaDocs anziché come tipi. L'interfaccia Comparator è un altro esempio ben noto che specifica quasi tutti i suoi vincoli nei documenti piuttosto che nei tipi. Oppure, prendi List.add , che non specifica nel suo tipo che l'implementazione abbia effettivamente bisogno di aggiungere un elemento alla lista, o List.sort , che non specifica nel suo tipo che le implementazioni devono effettivamente ordinare l'elenco, e così via e così via.

I programmatori Java sanno che i tipi non raccontano l'intera storia e che è necessario consultare la documentazione per un'immagine completa.

    
risposta data 29.08.2017 - 06:57
fonte
4

È certamente ragionevole che le interfacce specifichino che le implementazioni non fanno "una cosa". Questo modello può essere visto in C, C ++ e Fortran molto. Vedrai spesso cose chiamate precondizione (prima), postcondition (after), e raramente pericondition (cosa succede mentre la funzione / classe viene eseguita). Questo è stato ulteriormente ampliato in lingue che implementano effettivamente costrutti linguistici sotto forma di contratti . Spesso si vedono le condizioni pre e post su una funzione di template C ++, che definisce cosa può e non può essere usato al suo interno, quali proprietà deve avere il template (generics in java), ecc, nonostante non ci sia modo di farla rispettare (senza una metamodifica template molto difficile)

Nel tuo caso, tuttavia, non sono sicuro che l'intera classe debba essere immutabile o se solo la tua funzione debba essere immutabile invece dell'intera classe.

Nella tua situazione, invece di fornire limiti definiti dalla documentazione, potresti essere in grado di definire una classe che conterrà i dati a cui non vuoi accedere (presumendo che tu sappia anche cosa sia) che implementa solo gli accessor (che potrebbe essere tutto definitivo) e avere quella classe implementare l'interfaccia (o fornire un metodo astratto) per "eseguire". Non puoi garantire l'immutabilità nell'intera classe, ma puoi applicarla su un sottoinsieme di valori che conosci. Puoi anche usare la parola chiave final nella stessa classe astratta per ottenere un effetto simile (ma potrebbe essere più difficile da realizzare)

In altri linguaggi (come C ++) anche senza contratti è possibile forzare una funzione in "const", il che significa che non modifica la classe chiamante. Java rende queste cose particolarmente difficili da realizzare.

    
risposta data 30.08.2017 - 17:04
fonte
1

Se tutto ciò di cui hai bisogno è execute , non cambiare lo stato, quindi richiedere che l'istanza sia immutabile non è ragionevole. Anche nei casi più complessi, richiedendo che nessun metodo nell'interfaccia cambi lo stato sarebbe sufficiente.

Quando documenti pubblicamente questi requisiti non sono più dettagli di implementazione, vengono promossi a specifiche o contratti pubblici.

    
risposta data 30.08.2017 - 19:50
fonte

Leggi altre domande sui tag