Non c'è niente di sbagliato nell'avere un'interfaccia che erediti un'altra interfaccia senza aggiungere nuovi membri, se ci si aspetta che tutte le implementazioni di quest'ultima interfaccia siano in grado di utilmente fare cose che alcune implementazioni del precedente non può In effetti, è un buon modello che IMHO avrebbe dovuto essere usato più in cose come il .net Framework, specialmente dal momento che un implementatore la cui classe avrebbe naturalmente soddisfatto i vincoli implicati dall'interfaccia più derivata può indicare che semplicemente implementando l'interfaccia più derivata , senza dover modificare alcun codice o dichiarazione di implementazione dei membri.
Ad esempio, supponiamo di avere le interfacce:
interface IMaybeMutableFoo {
Bar Thing {get;set;} // And other properties as well
bool IsMutable;
IImmutableFoo AsImmutable();
}
interface IImmutableFoo : IMaybeMutableFoo {};
Ci si aspetta che l'implementazione di IImmutableFoo.AsImmutable()
ritorni da sola; una classe mutabile che implementa IMaybeMutableFoo.AsImmutable()
dovrebbe restituire un nuovo oggetto profondamente immutabile contenente un'istantanea dei dati. Una routine che vuole memorizzare un'istantanea dei dati contenuti in IMaybeMutableFoo
potrebbe offrire sovraccarichi:
public void StoreData(IImmutableFoo ThingToStore)
{
// Storing the reference will suffice, since ThingToStore is known to be immutable
}
public void StoreData(IMaybeMutableFoo ThingToStore)
{
StoreData(ThingToStore.AsImmutable()); // Call the more-specific overload
}
Nei casi in cui il compilatore non sappia che la cosa da memorizzare è un IImmutableFoo
, chiamerà AsImmutable()
. La funzione dovrebbe tornare rapidamente se l'elemento è già immutabile, ma una chiamata di funzione attraverso un'interfaccia richiede ancora tempo. Se il compilatore sa che l'elemento è già un IImmutableFoo
, può saltare l'inutile chiamata di funzione.