Allways调用base.Method Override而不提及简单的脚本

时间:2015-05-27 00:59:24

标签: c# game-engine

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

我有类BaseEntity。另一个来自BaseEntity的类BossEntity。然后我希望能够通过脚本创建一个新实体。所以我在我的脚本中创建了一个类,让我们说Boss1,它来自BossEntity。

BaseEntity有一个虚拟的更新方法。 BossEntity会覆盖它并调用base.Update()。一切都很好。

但现在我的问题。在我的脚本中,我也希望能够覆盖更新方法。所以我继续并再次覆盖它。所有工作都按照假设,BossEntity覆盖丢失,因为我现在再次覆盖BaseEntity更新。

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

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

所以我的一般问题是,有没有办法完成对base.Update()的调用,甚至没有在我的脚本中调用它?

我假设没有,或者只是一招,但你永远不会知道。

1 个答案:

答案 0 :(得分:4)

据我所知,当调用被覆盖的方法时,无法自动调用基类的虚方法。你必须明确地调用它。

您可以做的一件事是将父方法更多地打破。而不是将所有代码都放在像这样的单个可覆盖方法中:

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()方法抽象化,迫使孩子们实现它。这使得更加清晰,无需调用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.
    }
}

最后,这种方法可以让您的基类安全地处理其更新代码,方法是强制孩子实现他们自己不依赖的更新方法。您的基类可以在子类运行其更新之前和之后运行其更新内容。

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

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

您可以放心调用基类更新方法,并且也会调用子更新代码。