2011-09-28 16 views
8

Ho un sacco di sistemi, li chiamiamo A, B, C, D, E, F, G, H, I, J.Interfaccia, astratto o solo metodi virtuali?

Hanno tutti metodi e proprietà simili. Alcuni contengono lo stesso metodo e le stesse proprietà, alcuni possono variare leggermente e alcuni possono variare molto. Al momento, ho un sacco di codice duplicato per ogni sistema. Ad esempio, ho un metodo chiamato GetPropertyInformation() definito per ciascun sistema. Sto cercando di capire quale metodo sarebbe il metodo migliore per ridurre il codice duplicato o forse uno dei metodi indicati non è la strada da percorrere:

interfaccia

public Interface ISystem 
{ 
    public void GetPropertyInformation(); 
    //Other methods to implement 
} 

public class A : ISystem 
{ 
    public void GetPropertyInformation() 
    { 
     //Code here 
    } 
} 

astratta

public abstract class System 
{ 
    public virtual void GetPropertyInformation() 
    { 
     //Standard Code here 
    } 
} 

public class B : System 
{ 
    public override void GetPropertyInformation() 
    { 
     //B specific code here 
    } 
} 

metodi virtuali in una classe Super Base

public class System 
{ 
    public virtual void GetPropertyInformation() 
    { 
    //System Code 
    } 
} 

public class C : System 
{ 
    public override void GetPropertyInformation() 
    { 
     //C Code 
    } 
} 

Una domanda, anche se può essere stupido, è supponiamo sono andato con l'approccio astratto e ho voluto ignorare il GetPropertyInformation, ma avevo bisogno di passare un parametro in più, è possibile questo o avrei dovuto creare un altro metodo nella classe astratta? Ad esempio, GetPropertyInformation(x)

risposta

6

Gli approcci astratti e di "classe base super" non sono molto diversi. Dovresti sempre rendere astratta la classe base e puoi fornire un'implementazione predefinita (metodi virtuali) o meno (metodi astratti). Il fattore decisivo è se tu voglia mai avere istanze della classe base, penso di no.

Quindi è tra la classe base e l'interfaccia. Se esiste un forte accoppiamento tra le classi A, B C, è possibile utilizzare una classe base e probabilmente un'implementazione comune.

Se le classi A, B, C non appartengono naturalmente a una singola "famiglia", utilizzare un'interfaccia.

E System non è un buon nome.

E non è possibile modificare l'elenco parametri quando si esegue l'override. Forse i parametri di default possono aiutare, altrimenti hai solo bisogno di 2 overload per GetPropertyInformation().

+0

Ho avuto la sensazione che le classi astratte e super base fossero simili. I sistemi A, B, C hanno un forte accoppiamento. Esiste uno standard del settore, ma non deve essere seguito, in modo che ciascuno possa adottare lo standard o modificare lo standard per il fitting. In fretta, ho scelto System :) – Xaisoft

+0

Ottimi punti a proposito. – Xaisoft

3

In genere si sceglie l'ereditarietà dell'oggetto quando si desidera condividere l'implementazione e ridurre quello che altrimenti sarebbe la duplicazione. Altrimenti le interfacce vincono perché sono più flessibili poiché non c'è bisogno di una classe base comune.

Per quanto riguarda l'override di un metodo e la modifica dell'elenco dei parametri che non è possibile. Immagina come chiameresti quel metodo su una classe base o su un riferimento all'interfaccia?

+0

È "possibile" - dovresti essere in grado di dichiarare un tale metodo, non è più un override del metodo originale. – millimoose

+2

@Sii Certamente non è possibile. La domanda è stata posta per * sovrascrivere * il metodo e aggiungere un parametro. Questo non può essere fatto. –

+0

Avevo la sensazione che non potesse essere fatto, un pio desiderio. – Xaisoft

3

Vorrei andare con qualcosa di simile a quello che ho aggiunto di seguito. Otterrai comunque il vantaggio del contratto di interfaccia e dell'implementazione condivisa.

public Interface ISystem 
{ 
    public void GetPropertyInformation(); 
    //Other methods to implement 
} 

public abstract class System : ISystem 
{ 
    public virtual void GetPropertyInformation() 
    { 
     //Standard Code here 
    } 
} 

public class B : System 
{ 
    public string ExtendedSystemProp {get;set;} 

    public override void GetPropertyInformation() 
    { 
     base.GetPropertyInformation(); 

     var prop = "some extra calculating"; 

     GetExtraPropertyInformation(prop); 
    } 

    public void GetExtraPropertyInformation(string prop) 
    { 
     ExtendedSystemProp = prop; 
    } 
} 

ISystem genericSystem = new B(); 
genericSystem.GetPropertyInformation(); 

(genericSystem as B).ExtendedSystemProp = "value"; 
+0

Puoi spiegare perché dovresti fare questo approccio? – Xaisoft

+0

In questo modo, ottieni ancora tutte le tue proprietà anche quando stai programmando solo con l'interfaccia 'ISystem' (che dovresti fare quando le hai). Tuttavia, se si sta codificando in un contesto in cui esiste solo B: 'B bSystem = new B();' si espone anche il metodo specifico 'B' per uso esplicito. – scottm

2

Non è possibile passare il parametro supplementare nel override. Quando si esegue l'override, si sta sovrascrivendo il metodo con la firma esatta. Ti suggerisco di passare un parametro di interfaccia come IPropertyInformation che può cambiare per implementazione.

La decisione di utilizzare una classe base o un'interfaccia per l'implementazione dipende in realtà dall'utilizzo. A-I hanno abbastanza in comune tra loro che dovrebbero derivare tutti dalla stessa classe base? Se è così, allora usa una classe base. È davvero sufficiente condividere solo GetPropertyInformation e diversamente i sistemi sono completamente funzionalmente diversi? Quindi vuoi davvero che condividano un'interfaccia.

2

Altri hanno coperto ciò che era originariamente nella mia risposta, ma riguardo al punto "aggiungi un parametro": non dimenticare che l'ultimo C# ti consente anche di avere parametri opzionali nei metodi.

+0

Ma dovrei dichiarare parametri opzionali all'inizio. Potrei non sapere che ho bisogno di un parametro fino a 1 anno lungo la strada, quindi i parametri opzionali non mi fanno bene in questo caso. – Xaisoft

2

Se non si dispone di un motivo valido altrimenti, andrei con l'interfaccia. I metodi virtuali pubblici, benché fatti molto, sono not ideal.

Problemi correlati