总是在 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 更新代码也会被调用。
我正在尝试将 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 更新代码也会被调用。