【问题标题】:designing virtual methods设计虚拟方法
【发布时间】:2010-01-23 22:05:58
【问题描述】:

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

第一个设计:子方法必须调用基方法

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(); }
}

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

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

谢谢

【问题讨论】:

  • 我猜你自己已经回答过了。当您必须确保执行基本功能时,请使用第二种方法。
  • 其次是确定 OnEnable/Disable 是否受到保护而不是公开。

标签: c# virtual


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    我认为第二个template-based approach 更好。它允许您确保始终调用某些基本功能,并为您提供空间来添加一些(如果一开始不存在)而不会破坏任何子类的风险。

    【讨论】:

      【解决方案3】:

      一旦您将方法设为虚拟,您就给派生类一个破坏您的类的机会。一个负责任的派生者总是会问自己“我应该调用基本实现吗?”这方面的指导应始终来自文档。 MSDN 使用标准措辞:

      继承人须知:

      当覆盖派生的 Xxxxx 时 类,一定要调用基类 类的 Xxxx 方法,所以废话 发生。

      C# 语言使用“base”关键字使这一切变得简单。假设此文档不可用或不清楚,您的第二个示例将强烈阻止派生者调用其他基类方法。毕竟,她/他不会使用标准模式。仅当您希望阻止继承者调用基类方法时才使用此模式。

      【讨论】:

      • 我同意添加诸如虚拟方法之类的可扩展点会带来很多痛苦的机会,但我不确定我是否会将其描述为脆弱的基类问题。通常我认为脆弱的基类问题是一个派生类对基类的更改所破坏。
      【解决方案4】:

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

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

      第三种可能的情况可以满足,如果您采用示例 2 并对其进行更改,以便基类在设置标志之前调用 OnEnable:

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

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

      只是思考的食物。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-10-23
        • 2013-05-01
        • 2015-12-21
        • 1970-01-01
        • 2011-09-30
        • 2015-09-09
        • 1970-01-01
        相关资源
        最近更新 更多