我有一个抽象类CreatureBehaviour
,它提供了TakeTurn
方法。这样做的目的是决定生物应该做什么,它应该通过回调提供它的响应。这是因为响应可能需要玩家输入,所以它不应该阻止其他进程。
public abstract class CreatureBehaviour {
public abstract void TakeTurn (Action<TurnAction> response);
}
继承自此,PlayerControl
类存储response
回调以供以后决策。它的大多数内容都不相关,但最终它必须在玩家做某事时调用response
。
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.
}
所有非玩家生物也需要能够发送回调。为了安全起见,我想确保始终触发回调,因此我创建了一个抽象的NonPlayerControl
类来确保响应:
public abstract class NonPlayerControl : CreatureBehaviour {
protected abstract TurnAction TurnResponse ();
public override void TakeTurn (Action<TurnAction> response) {
response (TurnResponse ());
}
}
有了这个,我的所有非玩家生物行为都可以来自NonPlayerControl
,只需实现TurnReponse()
。编译器保证所有脚本都返回响应,而不是让回调挂起。请注意PlayerControl
无法实现TurnResponse()
,因为它需要保证立即返回,这会阻止其他进程。
所以我想从NonPlayerControl
派生其他类,也许从PlayerControl
派生,但我不想意外地从CreatureBehaviour
派生另一个类,并且有可能错过回调。
我有什么方法可以“封印”CreatureBehaviour
,以便它只能拥有这两个直接的孩子并阻止任何其他孩子?如果没有,我可以在这里使用更好的模式吗?
答案 0 :(得分:1)
你无法以“正常”的方式做到这一点,但是可以考虑一个选项......
如果您只为<a>
类提供私有构造函数,然后在该类中嵌套CreatureBehavior
和PlayerBehavior
,则可以访问私有构造函数但是没有其他课程......所以没有其他课程可以来自NonPlayerBehavior
。
更简单的解决方案是:
CreatureBehavior
中的文档,它不应该直接进行子类化当然,这只能测试你的代码而不是其他程序集中的代码。如果你不从其他程序集中需要这些,那么将这些类设为内部而不是公共。即使您需要公开所有类,也可以包含在CreatureBehavior
和PlayerBehavior
中实现的无操作抽象内部方法 - 这将阻止程序集之外的类派生自{{1}因为他们无法实现内部抽象方法。
答案 1 :(得分:1)
只是一个简单的想法,没有进一步测试:你可以使用通用来做限制吗?
public abstract class CreatureBehaviour<T> where T : IPlayerControl, INonPlayerControl {
// ...
}
然后以下列方式使用它:
public abstract class NonPlayerControl : CreatureBehaviour<NonPlayerControl>, INonPlayerControl {
// ...
}
public abstract class PlayerControl : CreatureBehaviour<PlayerControl>, IPlayerControl {
// ...
}
这有点像黑客,但它可能对你的情况有用。
答案 2 :(得分:0)
您不能禁止从CreatureBehavoiur类继承,但您可以通过组合内部密封和受保护访问来限制对TakeTurn方法的访问,并将其放在单独的程序集中:
public abstract class CreatureBehaviour
{
protected abstract void TakeTurn(Action<TurnAction> response);
}
public class PlayerControl : CreatureBehaviour
{
private Action<TurnAction> responseCallback;
protected override void TakeTurn(Action<TurnAction> response)
{
responseCallback = response;
}
internal void TurnByPlayer(Action<TurnAction> response)
{
TakeTurn(response);
}
// Various UI callbacks that can send something to "responseCallback" when appropriate.
}
public abstract class NonPlayerControl : CreatureBehaviour
{
protected abstract TurnAction TurnResponse();
protected override void TakeTurn(Action<TurnAction> response)
{
response(TurnResponse());
}
internal void TurnByNonPlayer(Action<TurnAction> response)
{
TakeTurn(response);
}
}
public sealed class CreatureStearing
{
public void Turn(PlayerControl control)
{
control.TurnByPlayer((action) => {});
}
public void Turn(NonPlayerControl control)
{
control.TurnByNonPlayer(action => {});
}
}
现在你可以从其他程序集中的PlayerControl,NonPlayerControl甚至CreatureBehaviour继承,但是你不能将TakeTurn方法用于PlayerControl和NonPlayerControl以外的任何类inance,它们位于不同的程序集中:
public class SomeTest1 : PlayerControl
{
protected override void TakeTurn(Action<TurnAction> response)
{
base.TakeTurn(response);
}
}
public class SomeTest2 : NonPlayerControl
{
protected override TurnAction TurnResponse()
{
throw new NotImplementedException();
}
protected override void TakeTurn(Action<TurnAction> response)
{
base.TakeTurn(response);
}
}
public class SomeTest3 : CreatureBehaviour
{
protected override void TakeTurn(Action<TurnAction> response)
{
throw new NotImplementedException();
}
}
....
var t1 = new SomeTest1();
var t2 = new SomeTest2();
var t3 = new SomeTest3();
var creatureStearing = new CreatureStearing();
creatureStearing.Turn(t1);
creatureStearing.Turn(t2);
creatureStearing.Turn(t3); // 'Cannot resolve method 'compile error here
当然,您可以通过声明程序集的内部访问来传递此限制,但它需要实现类似CreatureStearing的东西(以及一些努力),但在这种情况下,其他方将确定这是一个黑客。