设计虚拟方法

时间:2010-01-23 22:05:58

标签: c# virtual

我想知道在什么情况下你会选择第一种或第二种设计:

首先设计:子方法必须调用基本方法

public abstract class Base
{
    public virtual void Enable() { IsEnable = true;  }
    public virtual void Disable() { IsEnable = false; }
    public bool IsEnable { get; private set; }
}

public class Child : Base
{
    public override void Enable() { /* do stuffs */  base.Enable(); }
    public override void Disable() {  /* do stuffs */ base.Disable(); }
}

第二种设计:使用虚拟方法确保孩子不要忘记调用基础

public abstract class Base
{
    public void Enable()
    {
        IsEnable = true;
        OnEnable();
    }

    public void Disable()
    {
        IsEnable = false;
        OnDisable();
    }

    public bool IsEnable { get; private set; }
    public virtual void OnEnable() {}
    public virtual void OnDisable() {}
}

public class Child : Base
{
    override void OnEnable() { /* do stuffs */ }
    override void OnDisable() { /* do stuffs */ }
}

由于

4 个答案:

答案 0 :(得分:3)

这取决于您是否确实要确保IsEnable被设置。如果您可以想象用户不想设置它的场景,那么我想您可以将它留给他们来调用基本方法。否则,为他们做。

答案 1 :(得分:3)

第二,template-based approach在我看来更好。它允许您确保始终调用某些基本功能,并且如果最初没有任何基本功能,则可以添加一些功能,而不会有破坏任何子类的风险。

答案 2 :(得分:2)

只要你创建一个虚拟方法,你就会给派生类一个破坏你的类的机会。负责任的派生者总会问自己“我应该调用基础实现吗?”对此的指导应始终来自文档。 MSDN使用标准措辞:

  

对继承者的说明:

     

在派生中覆盖Xxxxx时   上课时,一定要打电话给基地   类的Xxxx方法让blablah   发生的情况。

使用“base”关键字,C#语言可以轻松实现。假设这个文档不可用或不清楚,你的第二个例子强烈反对派生者调用另一个基类方法。毕竟,他/她不会使用标准模式。仅当您希望阻止继承者调用基类方法时才使用此模式。

答案 3 :(得分:1)

在第一个中,覆盖类可以阻止设置Enable,我认为启用和禁用可能会误导方法名称。

像TryEnable和TryDisable这样的东西可能更准确,暗示有些情况下你无法启用。

第三种可能的情况可以照顾,如果您使用示例2并更改它,以便基类在设置标志之前调用OnEnable:

public void Enable()
{
    OnEnable(); // Exceptions raised from here prevent the flag being set.
    IsEnable = true;
}

然后,如果发生错误,则重写类可以通过引发异常来阻止设置标志。因此,错误情况会阻止标志被更改。

只是值得深思。