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?
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:
CreatureBehavior
that it shouldn't be subclassed directlyThat 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.
See more on this question at Stackoverflow