Risposta breve: No.
Risposta lunga: Esiste un compromesso tra l'uso di una classe e un'interfaccia. Le implementazioni dell'interfaccia possono essere scambiate in fase di runtime. Questo è bello perché è flessibile, ma significa anche che qualcuno può codificare un IFoo
non valido e passarlo a una delle tue funzioni altrimenti funzionante. Con un calcestruzzo (e sealed
/ final
) Foo
c'è solo un'implementazione, quindi se hai ragione, funziona sempre.
Un altro svantaggio delle interfacce è che non possono ispezionare i dettagli di implementazione degli altri membri di tale interfaccia. I metodi Foo
possono esaminare le variabili private di altri Foo
s, ma IFoo
s può solo guardare l'interfaccia di altri IFoo
s. Questo può limitare determinate ottimizzazioni, quindi se c'è solo un'implementazione di un'interfaccia può danneggiarti senza fornire alcun vantaggio.
Sfortunatamente i principali linguaggi OOP non forniscono un modo per scambiare implementazioni di classe. Idealmente, potresti essere in grado di avere più implementazioni Foo
e sceglierne una in fase di compilazione. Tuttavia, con un IDE non è difficile estrarre un'interfaccia da una classe dopo il fatto.
Se non è necessario manipolare più tipi di Foo
s nello stesso programma, non è necessario aggiungere un ulteriore livello di riferimento indiretto con un'interfaccia. Anche se hai bisogno di più tipi di Foo
s nello stesso programma, non hai necessariamente bisogno di un'interfaccia. Puoi avere una classe base astratta con un costruttore privato e implementare un numero finito di tipi di Foo
s come static final
sottoclassi interne. Vedi anche Come fare si codificano i tipi di dati algebrici in linguaggio C o Java .
Le interfacce brillano davvero quando non si desidera limitare il numero di possibili implementazioni utilizzabili in fase di runtime.
EDIT: per una spiegazione più approfondita dei trade-off coinvolti, vedi Informazioni sull'astrazione dei dati, rivisitate .