[英]C# generics, cross referencing classes for state pattern
I am trying to get into C# generics and have created a state machine with the state pattern and now I try to refactor. 我正在尝试使用C#泛型,并使用状态模式创建了状态机,现在我尝试进行重构。
I have a state, which has a reference to the object it's working on. 我有一个状态,该状态引用了它正在处理的对象。
public abstract class AbstractState<T> where T : StatefulObject {
protected T statefulObject;
public AbstractState(T statefulObject) {
this.statefulObject = statefulObject;
}
}
and I have the object which has states, this should have a reference to its current state. 并且我有具有状态的对象,这应该引用其当前状态。
public abstract class StatefulObject<T> : MonoBehaviour where T : AbstractState<StatefulObject<T>> {
public T state;
}
But it does not work ("the type cannot be used as type parameter 't' in the generic type or method"). 但这是行不通的(“该类型不能在通用类型或方法中用作类型参数't'”)。
What I want to achieve is something like this : 我想要实现的是这样的:
public class Monster : StatefulObject<MonsterState> {
}
public abstract class MonsterState : AbstractState<Monster> {
}
Is this possible? 这可能吗? If it's not this way, is there another?
如果不是这样,还有其他吗? Thx.
谢谢。
You can abuse interfaces and variance to achieve that: 您可以滥用接口和差异来实现以下目的:
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)
{
}
}
Whether it's actually a good idea is dubious, such code may be too confusing. 不管它实际上是一个好主意,还是令人怀疑的,这样的代码可能太令人困惑了。
You could also go with the simpler (but less strongly-typed) approach: 您还可以使用更简单(但类型不那么强)的方法:
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)
{
}
}
This won't ensure you won't be able to assign, say a PlayerState
to a Monster
, you should check that at runtime. 例如,这不能确保您无法将
Monster
分配给PlayerState
,您应该在运行时检查一下。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.