2012-02-16 23 views
5

Tengo el siguiente códigoClase de resumen, ¿cómo evitar la duplicación de código?

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 
    } 
} 

tengo estas clases de Suba y SubB que hereda de la clase base, se puede ver que tengo un código que repetirlo auto que está ajustando la hora, ¿hay una manera de mover la configuración del tiempo a la clase base?

Respuesta

3

Hay muchas soluciones posibles.

Esto depende de cuándo desea tener este conjunto de propiedades.

Si lo quiere de inmediato, puede hacerlo en el constructor de su clase 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

En este caso, SetTime debe estar protegido. – PVitt

2

utilizar un método virtual en lugar:

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 
{ 
} 

Todavía se puede reemplazar el método en las subclases en las que desea una implementación diferente.

5

se podría hacer algo como esto:

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. Exactamente lo que haría. – 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

base de referencia de verificación: http://msdn.microsoft.com/en-us/library/hfw7t1ce.aspx –

0

Hay un montón de respuestas ya. Como enfoque alternativo (y un poco ninja), sugeriré expresiones Lambda usadas con propiedades de método.

En su 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; 
    } 
    } 

De esta manera, nos proporcionan un comportamiento por defecto a la clase base. Con lambda expresiones se pueden crear instancias con diferentes métodos Invoke de la siguiente manera ..

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

El método de invocación se anula sólo para esta instancia de la clase Base. Esto le da más flexibilidad y ayuda a evitar la subclasificación innecesaria.

Compruebe esto awesome post from Patrick Steele para más detalles.

0

Existen dos opciones prácticas, según cuán rigurosos sean sus contratos de código.

Puede mover la lógica a un método virtual y permitir que los tipos secundarios sobrecarguen el comportamiento si así lo desean.

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 
    } 
} 

Sin embargo, esto hace posible que los tipos derivados no llamen al método base en absoluto.

Si es catastrófico si la funcionalidad de base no se invoca y se desea una mayor certeza del comportamiento esperado, es posible que desee hacer un contrato más fuerte, proporcionando un punto de inyección en el medio del método de 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 
    } 
} 
Cuestiones relacionadas