2013-02-21 17 views
10

Ho una classe astratta in un'API che viene utilizzata dai metodi in un altro assembly. La classe ha un enum nidificato definito al suo interno, un po 'come questo:Le interfacce non possono dichiarare i tipi

abstract public class Thing 
{ 
    public enum Status { Accepted, Denied, Pending }; 
    abstract public Status status { get; private set; } 
    etc... 
} 

Ho quindi deciso che sarebbe un design migliore se cosa era un'interfaccia. Ma non posso farlo:

public interface Thing 
{ 
    enum Status { Accepted, Denied, Pending }; 
    Status status { get; } 
    etc... 
} 

Questo produce il messaggio di errore "Le interfacce non possono dichiarare i tipi". Tuttavia, se spostassi la definizione dell'enum al di fuori dell'interfaccia, in primo luogo interromperò l'incapsulamento (il tipo Status appartiene veramente a Thing e non ha senso da solo) e, cosa più importante, dovrei andare a modificare il codice in i molti altri assembly che usano questo. Riesci a pensare a qualche soluzione?

+0

Se si è preoccupati per l'incapsulamento * breaking * (Non si incapsula dati membri in interfacce per definizione), si dovrebbe lasciare 'Thing' come classe. Non c'è niente di sbagliato nella tua classe base astratta. –

+0

trovato alcuni altri posti in cui è stata posta questa stessa domanda, questo commento su questo ha alcune buone opzioni. http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/14beb8d1-63d9-42f7-b036-eb9ebb106d08 in pratica, è possibile dichiarare l'enum altrove oppure utilizzare una classe di un'interfaccia .... e questo è tutto. Non c'è modo di fare esattamente quello che stai cercando di fare, più che peccato. – Nevyn

+4

L'argomento "incapsulamento" non ragiona con me e ti consiglierei di eliminare comunque il tipo nidificato pubblico. Se può essere esposto al mondo, allora trattalo come tale. –

risposta

13

Come indica l'errore, è sufficiente tirare la definizione di Status al di fuori dell'interfaccia. Capisco che rompa l'incapsulamento, ma non c'è davvero alcun modo per aggirare questo. Ti suggerisco di cambiare il nome di Status in qualcosa che indica una forte relazione a Thing - ThingStatus dovrebbe fare il trucco.

enum ThingStatus { Accepted, Denied, Pending }; 

public interface Thing 
{ 
    ThingStatus status { get; } 
    etc... 
} 
3

Sì, la soluzione è utilizzare una classe astratta se è necessaria tale implementazione. Le classi astratte non sono un cattivo design e sono certamente utili in situazioni come questa.

Se insisti a utilizzare le interfacce, temo che tu debba andare con la soluzione da p.s.w.g e infrangere una regola o due (quelle sono comunque solo linee guida, in realtà).

1

abstract classe e interface sono cose diverse. La classe abstarct è un'astrazione, superiore al modello di dominio e l'interfaccia è il contratto (comportamento) della tua entità di dominio. È possibile utilizzare entrambi nella soluzione, se necessario. Nello scenario concreto status non è il comportamento è solo stato di entità. Penso che la classe astratta sia una scelta più affidabile.

+0

Grazie per questo punto di vista, è qualcosa su cui riflettere. Come punto di interesse, nota come le classi astratte vengono utilizzate come interfacce in linguaggi che non hanno interfacce come parte della loro sintassi (il C++ è l'esempio ovvio). –

+0

@KlitosKyriacou Utilizzando la classe astratta come l'interfaccia può essere ottenuta dichiarando tutti i membri come astratti. Ma questo non è esattamente lo stesso in C#. –

Problemi correlati