2010-01-23 49 views
4

我在什么情况下你会选择第一或第二个设计纳闷:设计虚拟方法

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

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

感谢

+2

我猜你已经自己回答了。当你必须确保基本功能得到执行时使用第二种方法。 –

+0

第二个肯定的是,如果OnEnable/Disable已被beek保护而不是公开的。 –

回答

3

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

3

第二个,template-based approach在我看来更好。它允许您确保总是调用某些基本功能,并为您提供空间,以便在没有任何子类风险的情况下首先添加一些基本功能。

1

在第一个,overring类可以防止设置Enable,我认为启用和禁用可能是误导方法名称。

类似TryEnable和TryDisable可能会更准确地暗示有些情况下您无法启用。

第三个可能的情况可以照顾,如果你把例如2,改变它,因此基类设置标志前调用OnEnable:

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

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

只是思考的食物。

2

只要你使一个方法变成虚拟的,你就给派生类有机会打破你的课程。一个负责任的派生者总会问自己:“我应该打电话给基地实施吗?”对此的指导应始终来自文件。 MSDN使用标准的措辞:

给继承:

在派生 类中重写为Xxxxx,一定要调用基类 的XXXX方法,以便blablah 发生。

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

+0

我同意添加诸如虚拟方法之类的可扩展性点为疼痛提供了许多机会,但我不确定我是否将其描述为脆弱的基类问题。通常情况下,我认为脆弱的基类问题是*派生类*被基类*改变了。 –

+0

同意后,重新阅读您的博客文章。编辑。谢谢。 –