通用抽象类及其构造函数的问题

问题描述 投票:0回答:1

我正在尝试在 Unity 中制作一个可重用的状态机,据说可以处理常规状态和分层状态。

我有 3 个主要的抽象类,即 BaseState、StateMachine 和 StateFactory。

基础状态

public abstract class BaseState<EState>
        where EState : Enum
    {
        protected StateFactory<EState, BaseState<EState>> _factory;
        protected StateMachine<EState, BaseState<EState>> _machine;

        protected EState _stateKey;

        public BaseState(EState stateKey, StateMachine<EState, BaseState<EState>> machine, StateFactory<EState, BaseState<EState>> factory)
        {
            _stateKey = stateKey;
            _machine = machine;
            _factory = factory;
        }

        //Irrelevant logics
    }

分层基础状态

public abstract class HBaseState<EState> : BaseState<EState> where EState : Enum
    {
        //whether this state is a primary state
        protected bool _isRootState = false;

        //references to the parent and child of this state;
        protected HBaseState<EState> _parentState;
        protected HBaseState<EState> _childState;

        public HBaseState(EState stateKey, StateMachine<EState, HBaseState<EState>> machine, StateFactory<EState, HBaseState<EState>> factory, bool isRootState = false) : base(stateKey, *machine, factory*)
        {
            _stateKey = stateKey;
            _isRootState = isRootState;
        }
        
        //Irrelevant logics
    }

状态机

public abstract class StateMachine<EState, StateType> : MonoBehaviour 
        where EState : Enum
        where StateType : BaseState<EState>
    {
        protected StateFactory<EState, StateType> _factory;

        public StateType _currentState;

        //Irrelevant logics
    }

状态工厂

public abstract class StateFactory<EState, StateType> : MonoBehaviour
    where EState : Enum
    where StateType : BaseState<EState>
    {
        protected StateMachine<EState, StateType> _machine;

        protected Dictionary<EState, StateType> _statesCached = new Dictionary<EState, StateType>();

        public StateFactory(StateMachine<EState, StateType> machine, bool cacheStates = true)
        {
            _machine = machine;
            InstantiateStates();
        }

        protected abstract void InstantiateStates();

        //Irrelevant code
    }

当我尝试为继承 BaseState 的分层状态类创建构造函数时,出现问题。

显然 C# 无法将

StateMachine<EState, HBaseState<EState>>
转换为
StateMachine<EState, BaseState<EState>>
(上面的代码示例),因此我无法将参数从 HBaseState 传递到其基本 BaseState 构造函数。尝试过打字,但也不起作用。

我对泛型的实现一开始就正确吗?如何重构我的代码以使其正常工作?

这是我第一次使用 StackOverflow,非常感谢您的帮助和建议:D

c# unity-game-engine generics state-machine
1个回答
0
投票

显然 C# 无法将 StateMachine 转换为 StateMachine

这是正确的,因为这是两种不同的类型,没有任何可能允许转换的方差

在某些情况下,奇怪的重复模板模式可能会有所帮助。这可以帮助确保多个相关类型就

T
达成一致。即:

public abstract class Base<T> where T : Base<T>
{
    public StateMachine<T> Machine;
}

public class Derived1 : Base<Derived1>
{
    public void Test()
    {
        Derived1 current = base.Machine.CurrentState;
    }
}

public class Derived2 : Base<Derived2>
{
    public void Test()
    {
        Derived2 current = base.Machine.CurrentState;
    }
}

public class StateMachine<T> where T : Base<T>
{
    public T CurrentState { get; }
}

请注意,如果您想在同一状态机中使用多个不同的状态类型,这将无济于事。如果是这种情况,您需要使用普通的旧运行时多态性:

public abstract class Base
{
    public StateMachine Machine;
}

public class Derived1 : Base
{ }
public class StateMachine : Base
{
    public Base CurrentState { get; }
}

从经验来看,人们很容易将状态机之类的东西过度设计得过于通用和抽象。这通常会导致糟糕的结果,导致编译器错误,或者只是导致代码不可读。我的建议是从尽可能简单的开始,然后根据需要转向更复杂的模型。不要试图以可重用性的名义构建过于抽象和复杂的东西,因为复杂性可能会成为可重用性本身的障碍。

© www.soinside.com 2019 - 2024. All rights reserved.