Limit inheritance of intermediate abstract class

I have an abstract class, CreatureBehaviour, that provides a TakeTurn method. The goal of this is to decide what the creature should do, and it should provide its response via callback. This is because the response may require player input, so it shouldn't block other processes.

public abstract class CreatureBehaviour {

    public abstract void TakeTurn (Action<TurnAction> response);

}

Inheriting from this, the PlayerControl class stores the response callback for later decision-making. Most of its content isn't relevant, but ultimately it must invoke response when the player does something.

public class PlayerControl : CreatureBehaviour {

    Action<TurnAction> responseCallback;

    public override void TakeTurn(Action<TurnAction> response) {
        responseCallback = response;
    }

    // Various UI callbacks that can send something to "responseCallback" when appropriate.

}

And all non-player creatures need to be able to send a callback too. For safety, I want to ensure that a callback is always hit, so I've created an abstract NonPlayerControl class that ensures a response:

public abstract class NonPlayerControl : CreatureBehaviour {

    protected abstract TurnAction TurnResponse ();

    public override void TakeTurn (Action<TurnAction> response) {
        response (TurnResponse ());
    }

}

With this, all of my non-player creature behaviours can derive from NonPlayerControl and simply implement TurnReponse(). The compiler guarantees that all their scripts will return a response, rather than leaving the callback hanging. Note that PlayerControl can't implement TurnResponse() because it would need to guarantee an immediate return, and that would block other processes.

So I want to derive other classes from NonPlayerControl and maybe from PlayerControl, but I don't want to accidentally derive another class from CreatureBehaviour and risk missing the callback.

Is there any way I can "sort of seal" CreatureBehaviour so that it can only have these two direct children and prevent any others? If not, is there a better pattern I could be using here?

Jon Skeet
people
quotationmark

There's nothing you could do for this in a "normal" way, but there's one option you could consider...

If you give your CreatureBehavior class just a private constructor, then nest PlayerBehavior and NonPlayerBehavior within that class, they will have access to the private constructor but no other classes will... so no other classes could derive from CreatureBehavior.

A simpler solution would be to:

  • Document in CreatureBehavior that it shouldn't be subclassed directly
  • Write unit tests to validate that there aren't any other subclasses

That can only test your code rather than code in other assemblies, of course. If you don't need these from other assemblies, then make the classes internal instead of public. Even if you need all the classes to be public, you could include a no-op abstract internal method that's implemented in PlayerBehavior and NonPlayerBehavior - that will stop classes outside your assembly from deriving from CreatureBehavior as they can't implement the internal abstract method.

people

See more on this question at Stackoverflow