2012-05-29 6 views
24

Se un'interfaccia specifica una proprietà o un metodo per restituire un'altra interfaccia, perché non è consentito alle implementazioni della prima interfaccia di "modificare" il tipo restituito in un tipo più specifico?Perché l'implementazione dell'interfaccia non può restituire un tipo più specifico?

Facciamo un esempio per illustrare:

interface IFoo 
{ 
    IBar GetBar(); 
} 
interface IBar 
{ } 

class Foo : IFoo 
{ 
    // This is illegal, we are not implementing IFoo properly 
    public Bar GetBar() 
    { 
     return new Bar(); 
    } 
} 

class Bar : IBar 
{ } 

So come farlo funzionare, questo è non la mia preoccupazione.

posso solo uno:

  • Cambio tipo di ritorno di GetFoo()-IBar, o
  • esplicitamente implementare l'interfaccia e basta chiamare GetBar dalla IFoo.GetBar() metodo

Quello che sto veramente chiedendo è il ragionamento per non limitarsi a compilare il codice sopra. C'è qualche caso in cui quanto sopra non soddisfa il contratto specificato da IFoo.

+1

C'è un terzo modo, che è leggermente più conveniente rispetto ai due precedenti. È possibile implementare l'interfaccia con una classe astratta. E poi, nella tua classe "concreta" erediti la classe astratta invece dell'interfaccia. Quindi nella tua classe "concreta", puoi nascondere i metodi di base con la "nuova" parola chiave. Funziona decentemente per me. – BrainSlugs83

+0

Mi sento come il commento di BrainSlugs83 qui è una risposta in quanto fornisce una soluzione decente. –

risposta

17

In genere, direi che sarebbe il caso di bilanciare i vantaggi con la maggiore complessità del supporto di tale funzione. (Tutte le funzionalità si sforzano di progettare, documentare, implementare, testare e quindi gli sviluppatori devono essere educati anche su di loro.) Si noti che potrebbero esserci alcune complessità significative se si desidera supportare il ritorno di un tipo di valore che ha implementato un'interfaccia, ad esempio (come quello finisce in una rappresentazione diversa, piuttosto che solo un riferimento).

In questo caso, io non rispondo allo allo il CLR supporta anche tale funzione, il che renderebbe molto difficile per C# farlo in modo pulito.

Sono d'accordo che sarebbe una caratteristica utile, ma sospetto che non sia stato ritenuto abbastanza utile da giustificare il lavoro extra richiesto.

+7

Jon ho una domanda? Come scrivi così tanto in 1 minuto? –

+0

+1 perché il punto su "... ha aggiunto la complessità di ..." ma non sono sicuro che possa essere utile. Dopotutto un'interfaccia è un contratto, se hai bisogno di un metodo come quello puoi implementare esplicitamente il metodo di interfaccia e aggiungere un altro metodo con il tipo di reso _required_ quindi ... a cosa serve? –

+1

@Adriano: puoi, si. Ma è fastidioso doverlo fare, e l'implementazione esplicita dell'interfaccia ha i suoi lati negativi e le sue complessità. Evito l'implementazione esplicita dell'interfaccia dove posso, e se i tipi di ritorno covarianti fossero supportati, sarebbe un altro posto in cui potrei evitarlo :) –

3

La funzione che si sta chiedendo si chiama "covarianza del tipo di ritorno". Come notato on Wikipedia, Java e C++ hanno entrambi, il che forse rende sorprendente che C# non lo faccia.

Eric Lippert conferma nei commenti su questa risposta che questa funzione non è stata implementata perché non è stata considerata meritevole di implementazione. (Una precedente revisione di questa risposta ha assegnato personalmente a Eric la responsabilità di tale decisione, afferma che ciò non è corretto e che se una persona è responsabile è Anders Hejlsberg.)

Indipendentemente da ciò, ora ci sono varie proposte da aggiungere alla lingua (vedi https://github.com/dotnet/roslyn/issues/357, https://github.com/dotnet/csharplang/blob/master/proposals/covariant-returns.md, https://github.com/kingces95/coreclr/issues/2), quindi forse verrà implementato nei prossimi due anni. Per quelle discussioni, non sembra che ci siano motivi profondi per cui la funzione non dovrebbe esistere in C# in linea di principio - piuttosto, non è mai stato giudicato finora per il valore di nessuno sforzo da implementare.

+3

La funzionalità è stata aggiunta a Java un paio d'anni prima che facessi parte del team di progettazione C#, quindi la mia opinione non è stata presa in considerazione al momento. E mentre ero nel team di progettazione C#, a mio avviso la questione non era mai stata presa in considerazione dal team di progettazione. Sarebbe quindi più preciso dire che * Anders * non pensava che ne valesse la pena. Non penso che sia una brutta caratteristica, e lo userei se C# ce l'avesse. Sono d'accordo sul fatto che ci siano molte altre funzionalità che farei comunque con una priorità più alta. –