C# generics, перекрестные ссылки на классы для шаблона состояния
Я пытаюсь попасть в C# generics и создал государственную машину с шаблоном состояния, и теперь я пытаюсь рефакторинг.
у меня есть состояние, которое имеет ссылку на объект, над которым он работает.
public abstract class AbstractState<T> where T : StatefulObject {
protected T statefulObject;
public AbstractState(T statefulObject) {
this.statefulObject = statefulObject;
}
}
и у меня есть объект, который имеет состояния, это должно иметь ссылку на его текущее состояние.
public abstract class StatefulObject<T> : MonoBehaviour where T : AbstractState<StatefulObject<T>> {
public T state;
}
но он не работает ("тип не может использоваться в качестве параметра типа" t "в общем типе или методе").
что я хочу достичь чего-то вроде этого :
public class Monster : StatefulObject<MonsterState> {
}
public abstract class MonsterState : AbstractState<Monster> {
}
это возможно? Если это не так, есть еще? Тнх.
1 ответов
вы можете сообщил интерфейсы и дисперсия для достижения этого:
public interface IState<out TObject, in TState>
where TObject : IStatefulObject<TObject, TState>
where TState : IState<TObject, TState>
{
}
public interface IStatefulObject<in TObject, out TState>
where TObject : IStatefulObject<TObject, TState>
where TState : IState<TObject, TState>
{
}
public abstract class AbstractState<TObject> : IState<TObject, AbstractState<TObject>>
where TObject : IStatefulObject<TObject, AbstractState<TObject>>
{
protected TObject Object { get; private set; }
public AbstractState(TObject obj)
{
Object = obj;
}
}
public abstract class StatefulObject<TState> : IStatefulObject<StatefulObject<TState>, TState>
where TState : IState<StatefulObject<TState>, TState>
{
protected TState State { get; set; }
}
public class Monster : StatefulObject<MonsterState>
{
public Monster()
{
State = new IdleMonsterState(this);
}
}
public abstract class MonsterState : AbstractState<Monster>
{
protected MonsterState(Monster monster)
: base(monster)
{
}
}
public class IdleMonsterState : MonsterState
{
public IdleMonsterState(Monster monster)
: base(monster)
{
}
}
действительно ли это хорошая идея сомнительна, такой код может быть слишком запутанным.
вы также можете пойти с более простым (но менее сильно типизированным) подходом:
public abstract class AbstractState
{
}
public abstract class StatefulObject
{
}
public abstract class AbstractState<TObject> : AbstractState
where TObject : StatefulObject
{
protected TObject Object { get; private set; }
public AbstractState(TObject obj)
{
Object = obj;
}
}
public abstract class StatefulObject<TState> : StatefulObject
where TState : AbstractState
{
protected TState State { get; set; }
}
public class Monster : StatefulObject<MonsterState>
{
}
public abstract class MonsterState : AbstractState<Monster>
{
protected MonsterState(Monster monster)
: base(monster)
{
}
}
это не гарантирует, что вы не сможете назначить, скажем,PlayerState
до Monster
, вы должны проверить это во время выполнения.