delphi – 是否可以将枚举类型作为参数传递并在其他函数中重用此
我想要实现的就像虚拟代码:
type CommandSetOne = (Command1,Command2,Command3); CommandSetTwo = (Command4,Command5,Command6); TRobot = class procedure RegisterCommands(anyEnumerationType : TRttiEnumerationType); procedure ExecuteCommands(anEnumeration : theEnumerationType); end; 我可能有多组命令,命令集中的任何命令都是可替换的. TRobot有一个过程可以将枚举类型作为参数,他将保存此类型,将此类型用于ExecuteCommands过程. 关于传递任何枚举类型作为参数,我发现一种方法是使用TRttiEnumerationType,在调用方面它应该如下所示: var rttiContext : TRttiContext; typeref : TRttiType; RobotA : TRobot; begin rttiContext := TRttiContext.Create(); RobotA := TRobot.Create(); RobotA.RegisterCommands(rttiContext.GetType(TypeInfo(CommandSetOne))); end; 但我坚持传递Command1之类的命令.我已经为theEnumerationType尝试了Variant,但似乎我无法将Command1传递给它. 我知道如果我使用类似TStringList的东西,这是一个更容易的方法来做我想要的,但我想在符合时间的情况下通过delphi进行检查,以防我输入错误的命令(使用TstringList我可以添加代码来检查运行) 所以真正的问题是: >我应该为theEnumerationType使用哪种类型? 编辑: 感谢David建议,我应该使用两个Rtti的东西,所以为了说清楚,我添加了RegisterCommands的实现 implementation procedure TRobot.RegisterCommands(anyEnumerationType : TRttiEnumerationType); begin theEnumerationType := anyEnumerationType; end; procedure TRobot.ExecuteCommands (anyEnumerationValueoftheType : ???); begin //do something with the command end; 什么适合该类型的任何枚举值? 例如,如果我在RegisterCommands中使用CommandSetOne, 更具体地说,delphi只能为Command1或Command2或Command3限制空间吗?意味着如果我把Command4它给我一个编译错误? 解决方法
每当你发现自己想要将某种类型的东西作为参数传递时,goto解决方案就是泛型.
我们将滥用枚举实际上是一个整数不足的事实. TCommands = (Left,Right,Up,Down); TRobot = class private FRegisteredCommands: TDictionary<integer,string>; public procedure RegisterCommand<E: record>(Enum : E); procedure ExecuteCommand<E: record>(Enum : E); end; procedure TRobot.RegisterCommand<E: record>(Enum: E); var Key: integer absolute Enum; //typesafe,because of the if below. Info: PTypeInfo; begin if GetTypeKind(E) <> tkEnumeration then raise Exception.Create('Enum is not an enum'); //Added type safety: if not(TypeInfo(E) = TypeInfo(TRobotCommand1)) or not(TypeInfo(E) = TypeInfo(TRobotCommend2)) then raise .... Info:= TypeInfo(Enum); FRegisteredCommands.Add(Key,GetEnumName(Info,Key)); end; The compiler will remove all this 请注意,在早期的Delphi中,绝对指令会导致编译器内部错误(在西雅图,它可以100%正常工作).在这种情况下,更改代码如下: procedure TRobot.RegisterCommand<E: record>(Enum: E); var Key: integer; Info: PTypeInfo; begin .... Key:= PInteger(@Enum)^; ..... 如果给定的TRobot后代只接受单一类型的命令,那么我将泛型类型移动到TRobot,如下所示: TBaseRobot<E: record> = class(TObject) constructor Create; virtual; procedure RegisterCommand(Enum: E); //only implement once,see above. procedure ExecuteCommand(Enum: E); virtual; abstract; //implement in descendents. .... constructor TBaseRobot<E>.Create; begin inherited Create; if GetTypeKind(E) <> tkEnumeration then raise('error: details'); end; TRobotA = class(TBaseRobot<TMyEnum>) procedure ExecuteCommand(Enum: TMyEnum); override; end; .... 编辑 删除构造函数并将其替换为类构造函数,如下所示: //You should never name a class constructor `create`. class constructor don't create anything,they init stuff. class constructor TBaseRobot<E>.Init; begin if GetTypeKind(E) <> tkEnumeration then raise('error: details'); end; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |