![](/img/trans.png)
[英]Can I constrain a template parameter class to implement the interfaces that are supported by other?
[英]Force a class to implement an enum with no value constrain
我有不同的类别(例如:玩家,敌人,小行星...)-应该具有不同的状态之一(例如:确定,传送...)。
enum Status
{
Ok,
Teleporting,
...
};
使用接口 ,我想强制这些类仅声明它们内部是否存在枚举状态变量。 但是,我不希望值受到任何限制 。 也就是说,玩家和敌人的内部状态值可以不同(例如:一个可以传送,另一个可以不传送)。
我怎样才能做到这一点?
public enum Status
{
Ok,
Teleporting
};
public interface IHaveStatus
{
Status Status { get; set; }
}
public enum Status
{
Ok,
Teleporting
};
public interface IHaveStatus
{
Status status;
}
您可以如下声明接口:
public interface IHaveStatus {
Status Status { get; set; }
}
并让特定的类实现该接口:
class Player: IHaveStatus {
public Status Status { get; set; }
}
这不会限制status字段的使用,它可以具有对Status
枚举合法的任何值。
如果(但是)您想应用一些逻辑(敌人无法传送),那么这可能不是正确的设计。
如果要指定播放器具有某些功能(例如,传送),则可以使用属性或接口来标识那些类别。
使用接口:
public interface ICanTeleport { }
public class Player : ICanTeleport { ... }
您可以使用演员表确定能力:
if(somePlayer is ICanTeleport) { .. }
或使用属性时 :
[System.AttributeUsage(System.AttributeTargets.Class)]
public class Teleporter : System.Attribute
{ }
[Teleporter()]
public class Player { ... }
然后,您将必须使用反射来确定属性,请参阅此问题 。
使用接口使行为绑定到类继承。 它还使您有能力向接口添加方法(即Teleport(coordinates)
方法)。
使用属性可以使更多的可能的对象即时混合和匹配功能,因为没有类别层次会强制这些功能。
除非我遗漏了一些明显的东西,否则像这样的简单界面就可以做到:
public interface IHaveStatus
{
Status Status {get;}
}
我将在具体类中放入值约束。 例如,如果玩家无法传送,则在属性设置器中放置约束的好地方:
public class Player : IHaveStatus
{
private Status _status;
public Status Status
{
get {return _status;}
set
{
// a player can't teleport...
if(value != Status.Teleport)
{
_status = value;
}
}
}
}
您不能,至少不能使用相同的枚举类型。 您将必须为每组允许的值声明不同的枚举。 Pro:您可以进行编译时检查(只要您像Enums值那样通常显式地分配值)。 缺点:您必须为每个允许的范围声明一个新的Enum。
或者,您可以在运行时在setter
(方法或属性)的类型级别上检查传入的值,并在其中强制执行任何约束。 优点:整个范围只需要一个枚举。 缺点:此解决方案的缺点是您可能会遇到一些错误,直到运行时才能发现它们。
enum EnemyStatus
{
Ok
}
enum UserStatus
{
Ok,
Teleporting
}
class Enemy : IStatusable {
public Status CurrentStatus {
get {return _status;}
set {if(value == Status.Teleporting) throw new NotSupportedException();
this._status = value;
}}
}
interface IStatusable {
Status CurrentStatus {get;set;}
}
如果使用[Flags]
属性标记枚举,则可以在单个枚举字段中组合多个值:
[Flags]
enum Status
{
Ok = 0,
Teleporting = 1,
Flying = 2,
Dancing = 4
}
然后使用一个枚举属性声明接口:
interface Base
{
Status Abilities { get; }
}
class Player : Base
{
public Status Abilities { get; set; }
}
并测试对象的不同值,如下所示:
var p = new Player();
p.Abilities = Status.Ok | Status.Teleporting;
bool canTeleport = p.Abilities.HasFlag(Status.Teleporting);
bool canFly = p.Abilities.HasFlag(Status.Flying);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.