我有以下代码
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
}
}
我有这些从Base类继承的SubA和SubB类,你可以看到我有一个重复自我的代码,它设置了Time,有没有办法将时间设置移动到基类?
答案 0 :(得分:5)
你可以这样做:
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 :(得分:3)
有很多可能的解决方案。
这取决于您何时想要设置此属性。
如果您想立即使用它,可以在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
}
}
答案 2 :(得分: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
{
}
internal class SubB : Base
{
}
您仍然可以在需要不同实现的子类中覆盖该方法。
答案 3 :(得分: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
}
}
答案 4 :(得分:0)
已经有很多答案了。作为一种替代方法(以及一些忍者)的方法,我将建议使用方法属性的Lambda
表达式。
在你的情况下;
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;
}
}
这样,我们为base
类提供了默认行为。使用 lambda 表达式,您可以使用不同的Invoke
方法创建实例,如下所示。
var myInstance= new Base
{
Invoke = () => { Time = DateTime.Now.AddDays(7); }
};
仅对此Base
类的实例重写invoke方法。这提供了更大的灵活性,有助于避免不必要的子类化。
查看此awesome post from Patrick Steele了解详情。
答案 5 :(得分:0)
有两种实用选项,具体取决于您希望代码合同的严格程度。
您可以将逻辑移动到虚拟方法中,并允许子类型在他们选择的情况下重载行为。
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
}
}
然而,这确实使得派生类型根本不能调用基本方法。
如果没有调用基本功能并且您希望更加确定预期行为,那么它是灾难性的,您可能希望通过在基本方法的中间提供注入点来建立更强的契约:
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
}
}