Создание расширяемого конечного автомата

Я хотел бы создать базовый класс, представляющий конечный автомат, который затем будет расширен различными компонентами. Он должен быть настолько общим, насколько это возможно, и разрешать выполнение только состояниям, разработанным специально для этой машины. Это то, что я получил так далеко:

public interface IState<out T> where T : FiniteStateMachine {
    void Enter( T p );
    void Execute( T p );
    void Exit( T p );
}

public class FiniteStateMachine {
    public IState<FiniteStateMachine> CurrentState { get; private set; }

    public void ChangeState( IState<FiniteStateMachine> s ) {
        if ( CurrentState != null )
            CurrentState.Exit( this );

        CurrentState = s;
        s.Enter( this );
    }
}

public class Car : FiniteStateMachine { }
public class Boat : FiniteStateMachine { }

public class CarState : IState<Car> {
    public void Entra( Car f ) { }
    public void Esegui( Car f ) { }
    public void Esci( Car f ) { }
}

public class BoatState : IState<Boat> {
    public void Enter( Boat f ) { }
    public void Execute( Boat f ) { }
    public void Exit( Boat f ) { }
}

И вот небольшой пример:

var car = new Car( );
var boat = new Boat( );

// These are fine
car.ChangeState( new CarState( ) );
boat.ChangeState( new BoatState( ) );

// These aren't
car.ChangeState( new BoatState( ) );
boat.ChangeState( new CarState( ) );

В основном я хочу Car.ChangeState принимать только государства, которые реализуют IState<Car>, Boat.ChangeState принимать только IState<Boat> и так далее.

Я не могу добиться такого поведения, может ли кто-нибудь мне помочь?

1 ответ

Решение

По сути, я хочу, чтобы Car.ChangeState принимала только те состояния, которые реализуют IState<Car>, Boat.ChangeState принимать только IState<Boat> и так далее.

Типичный способ сделать это - использовать вариант шаблона Curiously Recurring Template. Я описываю C# версию шаблона здесь:

http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx

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

Другие вопросы по тегам