Попытка реализовать конечный автомат в C #, но не может преобразовать производный тип - PullRequest
0 голосов
/ 04 июня 2018

Я пытаюсь реализовать минимальный конечный автомат с классом контекста и несколькими классами состояний.

Вот два важных для меня правила:

  1. Класс контекста должен иметьнет реализации для класса состояний (добавление нового класса состояний не требует изменения класса контекста)
  2. Переход между состояниями осуществляется только в исходном состоянии

Здесь общая реализация:

public abstract class ContextState
{
    protected State<ContextState> currentState;
    public void Update()
    {
        currentState.Update();
    }
    public void SetState(State<ContextState> state)
    {
        currentState = state;
        state.Start(this);
    }
}

public abstract class State<C> where C:ContextState
{
    protected C context;

    public void Start(C context)
    {
        this.context = context;
    }
    abstract public void Update();
    abstract public void Exit();

    protected void SetNewState<S>() where S : State<ContextState>,new()
    {
        Exit();
        context.SetState(new S());
    }
}

Теперь я пытаюсь реализовать эти классы для реального приложения:

public class CarConfigurationContext : ContextState
{
    public CarConfigurationContext()
    {
        SetState(new PlayCarState());
    }

}

public class PlayCarState : State<CarConfigurationContext>
{
    public override void Exit()
    {
        ...
    }

    public override void Update()
    {
        ...
    }
}

У меня ошибка компиляции при SetState(new PlayCarState()); Невозможное преобразование из PlayCarState в State<ContextState>

После поиска в stackoverflow одним из возможных решений было бы использование интерфейса вместо абстрактного класса, но я хочу сохранить мою общую реализацию в ContextState и State.

Если у вас есть идеи о том, как я могу разрешитьэто, сохраняя ту же концепцию, что и у меня, я был бы признателен.

Спасибо

Примечание: у меня также есть проблема кругового референсано я еще не думаю об этом.

note2: универсальная реализация не закончена, я на самом деле думаю о том, какие методы должны быть виртуальными, а где должны вызываться Start и Exit

1 Ответ

0 голосов
/ 04 июня 2018

На данный момент единственное решение, которое я нашел, - это изменить реализацию класса State на PlayCarState:State<ContextState>, а затем выполнить динамическое приведение из ContextState к CarContextState в методе Start.Это частично безопасно и чисто, но мне интересно, есть ли еще лучшее решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...