总是在 Override 中调用 base.Method 而对于简单的脚本不提及它

Allways call base.Method in Override without mentioning it for simple Scripts

我正在尝试将 C# 实现为我的游戏引擎的脚本语言。一切正常,我的设计只出现了一个大问题。

我有 class BaseEntity。另一个 class BossEntity 派生自 BaseEntity。然后我希望能够通过脚本创建一个新实体。所以我在我的脚本中创建了一个 class 比方说 Boss1,它派生自 BossEntity。

BaseEntity 有一个虚拟更新方法。 BossEntity 覆盖它并调用 base.Update()。一切都在设计中。

但现在是我的问题。在我的脚本中,我还希望能够覆盖更新方法。所以我继续并再次覆盖它。一切正常,BossEntity 覆盖丢失,因为我现在再次覆盖 BaseEntity 更新。

但为简单起见,我不想在我的脚本中调用 base.Update() 以获得与 BossEntity 中相同的行为。这是一个可以被遗忘的事情,对于我来说,对于脚本语言来说,这是糟糕的设计。

在我看来,编写脚本时您只是添加功能而不是删除某些功能。

所以我的一般问题是,有没有什么方法可以完成对 base.Update() 的调用,而无需在我的脚本中额外调用它?

我假设没有,或者可能只是用了一个把戏,但你永远不知道。

据我所知,当调用重写的方法时,无法自动调用基础 class 的虚方法。您必须明确调用它。

您可以做的一件事是进一步分解 parent 方法。而不是像这样将所有代码都放在一个可覆盖的方法中:

public class Foo
{
    public virtual void Update()
    {
        // Do stuff
    }
}

public class Bar : Foo
{
    public override void Update()
    {
        // Replaces the parents implementation of the 
        // Update method due to not calling base.Load();
    }
}

相反,您可以使用 Template Method Pattern 将其分成多个部分,以便用户可以覆盖明确为他们准备的部分。

public class Foo
{
    public void Update()
    {
        this.OnUpdating();
        this.PerformUpdate();
        this.OnUpdated();
    }

    public virtual void PerformUpdate()
    {
        // Leave this empty. Let the subclass override it and
        // do their own thing. Your parent code will still
        // get called when Update() is called.
    }

    public void OnUpdating()
    {
        // Invoke code that you want to guarantee is always
        // executed PRIOR the overridden PerformUpdate() method
        // is finished.
    }

    public void OnUpdated()
    {
        // Invoke code that you want to guarantee is always
        // executed AFTER the overridden PerformUpdate() method
        // is finished.
    }
}

public class Bar : Foo
{
    public override void PerformUpdate()
    {
        // Do custom stuff, don't have to call base.PerformUpdate()
        // because it already does it's code in OnUpdating() 
        // and OnUpdated().
    }
}

希望这是有道理的。这就是我在我的游戏引擎中所做的。然后我记录不需要调用 base.PerformUpdate() 。另一种选择是将 PerformUpdate() 方法抽象化,强制 children 来实现它。这使得无需调用 base.PerformUpdate().

变得更加清楚
public class Foo
{
    public void Update()
    {
        this.OnUpdating();
        this.PerformUpdate();
        this.OnUpdated();
    }

    // Child class is required to implement this method. 
    // Only downside is you will no longer be able to instance 
    // the base class. If that is acceptable, then this is really 
    // the preferred way IMO for what you are wanting to do.
    public abstract void PerformUpdate();

    public void OnUpdating()
    {
        // Invoke code that you want to guarantee is always 
        // executed PRIOR the overridden PerformUpdate() method is finished.
    }

    public void OnUpdated()
    {
        // Invoke code that you want to guarantee is always 
        // executed AFTER the overridden PerformUpdate() method is finished.
    }
}

最后,这种方法通过强制 children 实现他们自己不依赖的更新方法,让您的基础 class 安全地处理其更新代码。您的基地 class 可以 运行 通过它的更新内容 child-class 在 运行 通过它的更新之前和之后。

这基本上可以让您在游戏代码中执行此操作:

Bar myFoo = new Bar();
myFoo.Update();

您可以放心,您的基础 class 更新方法会被调用,child 更新代码也会被调用。