我刚刚开始尝试使用一些抽象类和继承来编写一个有限状态机,其中状态和状态机可以被继承,以便该框架可以用于不同类型的 AI。
问题是继承的类一直期待其参数的基类型,不接受派生类型,我不确定我是在以错误的方式处理它还是只是以错误的方式编码。 (据我了解,我正在尝试实现 Liskov Substitution Principle )
基本代码:
public abstract class State {
public abstract void BeginState(StateMachine stateMachine);
public abstract void UpdateState(StateMachine stateMachine);
public abstract void EndState(StateMachine stateMachine);
}
public class StateMachine : MonoBehaviour {
//Stuff here to execute the current state, store previous state, revert states, etc.
//Example:
private State currentState;
private State previousState;
public virtual void SwitchState(State newState) {
//Switch state, store previous state if not null
if (currentState != null) {
previousState = currentState;
currentState.EndState(this);
}
currentState = newState;
currentState.BeginState(this);
}
}
这个想法是,这些可以被继承和扩展,以用于人类 ai、僵尸 ai、机器人 ai 等:
public class Idle : State
{
//Begin, Update, and End states here. Example:
public override void BeginState(ZombieStateMachine ZSM)
{
Debug.Log("Begin idling");
}
}
public class ZombieStateMachine : StateMachine {
public Idle idleState = new Idle();
void Start {
SwitchState(idleState);
}
}
问题出在继承自抽象 State 类的 Idle 状态。我正在尝试通过继承了 StateMachine 的 ZombieStateMachine,但是 Idle 类抛出错误,而是期望 StateMachine。 (编辑:该错误是编译时错误,而不是我错误暗示的运行时错误)
如有任何帮助,我们将不胜感激。
最佳答案
这是否如您的描述所暗示的那样是运行时错误?或者这是一个编译时错误?我怀疑是后者,因为:
public override void BeginState(ZombieStateMachine ZSM)
实际上并没有覆盖这个:
public abstract void BeginState(StateMachine stateMachine)
覆盖需要是相同的类型:
public override void BeginState(StateMachine ZSM)
在这种情况下,里氏替换原则的想法是 BeginState
方法中的任何内容都不应该关心它所提供的StateMachine
的种类,它应该只与基本的 StateMachine
操作交互。
您的两个基类相互传递似乎有点奇怪。 State
上的方法需要一个 StateMachine
,而 StateMachine
上的方法需要一个 State
。目前还不清楚为什么会这样。
虽然如果确实需要这样,那么我想知道您是否可以从泛型基类型中受益。像这样:
public abstract class State<T> where T : StateMachine
{
public abstract void BeginState(T stateMachine);
public abstract void UpdateState(T stateMachine);
public abstract void EndState(T stateMachine);
}
然后用指定的类型继承:
public class Idle : State<ZombieStateMachine>
{
//Begin, Update, and End states here. Example:
public override void BeginState(ZombieStateMachine ZSM)
{
Debug.Log("Begin idling");
}
}
这是徒手编写的代码,所以我不是100% 确定它是否有效,但对我来说似乎是合理的。 (如果不正确,我会继续并删除此答案。)
这种种类限制了您尝试的纯多态性,因为子类型不再接受任何实现基类型的类型。但看起来这就是您对用法的期望,一个类的给定子类型本质上将与另一个类的相应子类型“配对”。通过使用泛型,它们可以显式配对。
关于c# - 需要帮助使用继承来接受有限状态机中的派生类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32145195/