2012-02-16 10 views
5

Ho il seguente codice diClasse astratta, come evitare la duplicazione del codice?

internal abstract class Base 
{ 
    public DateTime Time; 
    public string Message; 
    public string Log; 
    public abstract void Invoke(string message); 
} 

internal class SubA : Base 
{ 
    public override void Invoke(string message) 
    { 
     Time = DateTime.Now; 
     // Do A 
    } 
} 

internal class SubB : Base 
{ 
    public override void Invoke(string message) 
    { 
     Time = DateTime.Now; 
     // Do B 
    } 
} 

ho queste classi Suba e Subb che eredita dalla classe base, si può vedere che ho un codice che ripeterlo sé che è l'impostazione del tempo, c'è un modo per sposta l'impostazione dell'ora nella classe base?

risposta

3

Ci sono molte soluzioni possibili.

Questo dipende da quando si desidera avere questo set di proprietà.

Se lo si desidera immediatamente, è possibile farlo nel costruttore della classe Base.

internal abstract class Base 
{ 
    public DateTime Time; 
    public string Message; 
    public string Log; 
    public abstract void Invoke(string message); 

    public Base() 
    { 
     Time = DateTime.Now; 
    } 
} 

internal class SubA : Base 
{ 
    public override void Invoke(string message) 
    { 
     // Do A 
    } 
} 

internal class SubB : Base 
{ 
    public override void Invoke(string message) 
    { 
     // Do B 
    } 
} 
+0

In questo caso SetTime deve essere protetto. – PVitt

2

utilizzare un metodo virtuale invece:

internal abstract class Base 
{ 
    public DateTime Time; 
    public string Message; 
    public string Log; 
    public virtual void Invoke(string message) { 
     Time = DateTime.Now; 
    } 
} 

internal class SubA : Base 
{ 
} 

internal class SubB : Base 
{ 
} 

È comunque possibile eseguire l'override del metodo in sottoclassi in cui si desidera un'implementazione diversa.

5

Si potrebbe fare qualcosa di simile:

internal abstract class Base 
{ 
    public DateTime Time; 
    public string Message; 
    public string Log; 
    public void Invoke(string message){ 
     Time = DateTime.Now; 
     this.InvokeInternal(message); 
    } 
    protected abstract void InvokeInternal(string message); 
} 

internal class SubA : Base 
{ 
    protected override void InvokeInternal(string message) 
    { 
     // Do A 
    } 
} 

internal class SubB : Base 
{ 
    protected override void InvokeInternal(string message) 
    { 
     // Do B 
    } 
} 
+1

+1. Esattamente quello che vorrei fare. – Jehof

2
internal abstract class Base 
{ 
    public DateTime Time; 
    public string Message; 
    public string Log; 
    public virtual void Invoke(string message) 
    { 
     Time = DateTime.Now; 
    } 

} 

internal class SubA : Base 
{ 
    public override void Invoke(string message) 
    { 
     base.Invoke(message); 
     // Do A 
    } 
} 

internal class SubB : Base 
{ 
    public override void Invoke(string message) 
    { 
     base.Invoke(message); 
     // Do B 
    } 
} 
+0

riferimento base di controllo: http://msdn.microsoft.com/en-us/library/hfw7t1ce.aspx –

0

Ci sono un sacco di risposte già. Come alternativa (e un po 'di ninja), ti suggerirò le espressioni Lambda usate con le proprietà del metodo.

Nel tuo caso;

public class Base 
    { 
    public DateTime Time; 
    public string Message; 
    public string Log; 
    public Action<string> Invoke { get; set; } 

    public Base() 
    { 
     this.Invoke = InvokeDefault; 
    } 

    private void InvokeDefault(string message) 
    { 
     Time = DateTime.Now; 
    } 
    } 

In questo modo, viene fornito un comportamento predefinito alla classe base. Con lambda espressioni è possibile creare istanze con diversi metodi Invoke come segue ..

var myInstance= new Base 
    { 
    Invoke =() => { Time = DateTime.Now.AddDays(7); } 
    }; 

il metodo Invoke viene sovrascritto solo per questa istanza della classe Base. Ciò conferisce maggiore flessibilità e aiuta a evitare sottoclassi non necessarie.

Controllare questo awesome post from Patrick Steele per i dettagli.

0

Esistono due opzioni pratiche, a seconda del livello di rigorosità dei contratti di codice.

È possibile spostare la logica in un metodo virtuale e consentire ai tipi di bambino di sovraccaricare il comportamento se lo desiderano.

internal abstract class Base 
{ 
    ... 
    public virtual void Invoke(string message) 
    { 
     Time = DateTime.Now; 
    } 
} 

internal class SubA : Base 
{ 
    public override void Invoke(string message) 
    { 
     base.Invoke(message); 
     // Do A 
    } 
} 

internal class SubB : Base 
{ 
    public override void Invoke(string message) 
    { 
     base.Invoke(message); 
     // Do B 
    } 
} 

Ciò tuttavia rende possibile che i tipi derivati ​​non chiamino affatto il metodo di base.

Se è catastrofica se la funzionalità di base non viene richiamato e si desidera maggiore certezza del comportamento previsto, si potrebbe desiderare di fare un contratto più forte attraverso un punto di iniezione nel mezzo del metodo di base:

internal abstract class Base 
{ 
    ... 
    public void Invoke(string message) 
    { 
     Time = DateTime.Now; 
     this.InvokeCore(message); 
    } 

    protected abstract void InvokeCore(string message); 
} 

internal class SubA : Base 
{ 
    public override void Invoke(string message) 
    { 
     // Do A 
    } 
} 

internal class SubB : Base 
{ 
    public override void InvokeCore(string message) 
    { 
     // Do B 
    } 
} 
Problemi correlati