23

我可以以某种方式强制派生类始终调用被覆盖的方法基吗?

public class BaseClass
{
    public virtual void Update()
    {
        if(condition)
        {
            throw new Exception("..."); // Prevent derived method to be called
        }
    }
}

然后在派生类中:

public override void Update()
{
    base.Update(); // Forced call

    // Do any work
}

我搜索并找到了使用非虚拟 Update() 以及受保护的虚拟 UpdateEx() 的建议。就是感觉不是很整洁,有没有更好的办法?

我希望你能得到这个问题,对于任何糟糕的英语,我深表歉意。

4

4 回答 4

32

使用模板方法模式——不要覆盖需要做一些工作的基方法,覆盖一个特定的位,它可以是抽象的,也可以是基类中的无操作。(关于是使其成为无操作还是抽象的决定通常是相当明显的——基类本身是否有意义,作为一个具体类?)

听起来这基本上是您发现的模式UpdateEx- 尽管UpdateImpl在我的经验中它通常或类似的东西。在我看来,这作为一种模式没有任何问题——它避免了强制所有派生类编写相同代码来调用基方法的任何想法。

于 2010-05-31T17:49:13.093 回答
4

我花了一点时间才知道 Update 和 UpdateEx 的样子。这是一个可能对其他人有帮助的代码示例。

public class BaseClass
{
    // This is the Update that class instances will use, it's never overridden by a subclass
    public void Update()
    {
        if(condition);
        // etc... base class code that will always run

        UpdateEx(); // ensure subclass Update() functionality is run
    }

    protected virtual void UpdateEx()
    {
        // does nothing unless sub-class overrides
    }
}

子类永远不会有任何 Update() 实现。它将使用 UpdateEx() 将实现添加到 Update();

public class ConcreteClass : BaseClass
{
    protected override void UpdateEx()
    {
        // implementation to be added to the BaseClass Update();
    }
}

ConcreteClass 的任何实例都将使用 Update() 的 BaseClass 实现,但是 ConcreteClass 使用 UpdateEx() 扩展它。

于 2015-05-08T20:16:49.263 回答
2

我认为您找到的建议很好。

您无法避免从基类构造函数中的子类调用的唯一基类方法。

于 2010-05-31T17:48:43.593 回答
2

我认为拥有一个调用可以扩展的虚拟“钩子”的非虚拟基本成员是此类问题的最常见解决方案。

根据您的用例,您可能希望使用 anevent来代替,但实现事件的通常模式是拥有一个OnEvent子类可以覆盖的虚拟方法,而不是添加事件处理程序,因此在您的示例情况下,它归结为相同事物。

于 2010-05-31T17:49:04.487 回答