简体   繁体   English

是否可以要求派生 class 从基 class 实现虚方法?

[英]Is it possible to require a derived class to implement a virtual method from base class?

I want a method to do a consistent thing in base class while derived classes can have it do something different (hence it being virtual), while requiring it be implemented in derived classes as if it were abstract.我想要一个方法在基 class 中做一致的事情,而派生类可以让它做一些不同的事情(因此它是虚拟的),同时要求它在派生类中实现,就好像它是抽象的一样。 It being required would prevent forgetfulness of implementing it among myself and others working on it.它被要求将防止忘记在我自己和其他从事它工作的人之间实施它。

To break it down (this code is for a Unity project):将其分解(此代码用于 Unity 项目):

// Base
public abstract class Attack : MonoBehaviour
{
    public virtual void AttackFinished()
    {
        Entity.StateController.SwitchToState<IdleState>();
    }
}

// Child
public class PlayerSwordAttack : Attack
{
    // I want this implementation to be required, not optional
    // while having it still do the stuff it does in base
    public override void AttackFinished()
    {
        base.AttackFinished();
        // Extra stuff
    }
}

In this case, I want PlayerSwordAttack or any other child classes to require implementing AttackFinished() without it being abstract.在这种情况下,我希望PlayerSwordAttack或任何其他子类需要实现AttackFinished()而不是抽象的。

Tl;dr: Essentially I want public abstract virtual void AttackFinished() which isn't possible as far as I know, but I hope to learn of a way to do it. Tl; dr:本质上我想要public abstract virtual void AttackFinished()据我所知这是不可能的,但我希望学习一种方法来做到这一点。

Given that I haven't found this question posted here or anywhere else, I'm expecting the answer to be "don't be silly, it's impossible" but thought I'd ask, since a friend of mine has had the same question.鉴于我没有在此处或其他任何地方找到此问题,我希望答案是“别傻了,这是不可能的”,但我想我会问,因为我的一个朋友有同样的问题.

Just break it down into two methods.只需将其分解为两种方法即可。 One is non-virtual, non-abstract, so is not overridable.一种是非虚拟的、非抽象的,因此不可覆盖。 This will call the abstract method that derived classes are forced to implement.这将调用派生类强制实现的抽象方法。

public abstract class Attack
{
    public void AttackFinished()
    {
        Entity.StateController.SwitchToState<IdleState>();
        OnAttackFinished();
    }
    
    protected abstract void OnAttackFinished();
}

public class PlayerSwordAttack : Attack
{
    protected override void OnAttackFinished()
    {
        // Extra stuff
    }
}

Note that this is like forcing base.AttackFinished in your original code to be called in the derived classes' implementations.请注意,这就像强制在派生类的实现中调用原始代码中的base.AttackFinished一样。 If you want derived classes to opt out of this, you can add an additional property:如果你想让派生类选择退出这个,你可以添加一个额外的属性:

public abstract class Attack
{
    public void AttackFinished()
    {
        if (ShouldChangeStateAfterAttack) {
            Entity.StateController.SwitchToState<IdleState>();
        }
        OnAttackFinished();
    }
    
    protected abstract void OnAttackFinished();
    
    // could also be virtual instead to provide a default implementation
    protected abstract bool ShouldChangeStateAfterAttack { get; }
}

public class PlayerSwordAttack : Attack
{
    protected override void OnAttackFinished()
    {
        // Extra stuff
    }

    protected override bool ShouldChangeStateAfterAttack => false;
}

base.AttackFinished in your original code could also be called independently, from anywhere in the derived class. If you also want that, simply extract the line Entity.StateController.SwitchToState<IdleState>();原始代码中的base.AttackFinished也可以从派生的 class 中的任何位置独立调用。如果您还需要,只需提取行Entity.StateController.SwitchToState<IdleState>(); as another method.作为另一种方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM