Delphi - 带有变体部分的记录
Posted
技术标签:
【中文标题】Delphi - 带有变体部分的记录【英文标题】:Delphi - records with variant parts 【发布时间】:2011-10-26 11:10:17 【问题描述】:我想要一个带有“多态”的记录(结构)。它将在所有情况下使用几个字段,我只想在需要时使用其他字段。我知道我可以通过在记录中声明的变体部分来实现这一点。我不知道是否有可能在设计时我只能访问我需要的元素。更具体地说,请看下面的示例
program consapp;
$APPTYPE CONSOLE
uses
ExceptionLog,
SysUtils;
type
a = record
b : integer;
case isEnabled : boolean of
true : (c:Integer);
false : (d:String[50]);
end;
var test:a;
begin
test.b:=1;
test.isEnabled := False;
test.c := 3; //because isenabled is false, I want that the c element to be unavailable to the coder, and to access only the d element.
Writeln(test.c);
readln;
end.
这可能吗?
【问题讨论】:
【参考方案1】:无论标签的值如何,变体记录中的所有变体字段都可以随时访问。
为了实现您正在寻找的可访问性控制,您需要使用属性并进行运行时检查来控制可访问性。
type
TMyRecord = record
strict private
FIsEnabled: Boolean;
FInt: Integer;
FStr: string;
// ... declare the property getters and settings here
public
property IsEnabled: Boolean read FIsEnabled write FIsEnabled;
property Int: Integer read GetInt write SetInt;
property Str: string read GetString write SetString;
end;
...
function TMyRecord.GetInt: Integer;
begin
if IsEnabled then
Result := FInt
else
raise EValueNotAvailable.Create('blah blah');
end;
【讨论】:
这是完全正确的,但在这种情况下,我宁愿使用类而不是记录。它将允许添加继承功能,这在这里很有意义(例如,IsEnable 属性通常在父级处理,并在子级之间共享)。【参考方案2】:即使我听说按照最初的 Niklaus Wirth 的 Pascal 定义,一切都应该像你预期的那样工作,我在 Delphi 中没有看到这样的行为,从它的祖先 Turbo Pascal 2.0 开始。快速查看 FreePascal 表明 its behaviour 是相同的。如Delphi documentation中所说:
您可以随时读取或写入任何变体的任何字段;但是,如果您先写入一个变体中的字段,然后再写入另一个变体中的字段,则可能会覆盖您自己的数据。该标签(如果有的话)作为记录的非变体部分中的一个额外字段(类型为 ordinalType)。”
关于你的意图,据我了解,我会使用两个不同的类,有点
a = class
b : Integer
end;
aEnabled = class(a)
c: Integer
end;
aDisabled = class(a)
d: String //plus this way you can use long strings
end;
这样,即使在设计时,您也可以从 IDE 的代码编辑器中获得一些支持。不过,更有用的是,以后修改和支持会更容易。
但是,如果您需要在运行时快速切换记录变量值,@David Heffernan's variant 使用属性并进行运行时检查更合理。
【讨论】:
【参考方案3】:给出的示例不是变体记录,它始终包含所有字段。
真正的变体记录具有共享相同内存的变体。您只需使用“case discriminator: DiscType of .....”语法,无需单独的字段告诉您哪些变体处于活动状态。
【讨论】:
是变体记录。情况就是这样。 你说的是 absolute 变量,这是另一回事。大卫是对的,这是一个变体记录。 它不包括所有字段,而是提供对case
之后的所有部分的访问权限同时,并且所有这些部分共享相同的内存。所以它类似于 absolute vars,除了:它更结构化;你有标签变量;并且,内存对齐可能有点不同以上是关于Delphi - 带有变体部分的记录的主要内容,如果未能解决你的问题,请参考以下文章