Delphi - 包含变体部分的记录

时间:2011-10-26 11:10:17

标签: delphi delphi-2009 record

我想要一个带有多态性的记录(结构)'行为举止。在所有情况下都会使用几个字段,我只想在需要时才使用其他字段。我知道我可以通过记录中声明的变体部分来实现这一点。我不知道在设计时我是否有可能只访问我需要的元素。更具体地说,请看下面的示例

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.

这可能吗?

3 个答案:

答案 0 :(得分:8)

无论标签的价值如何,都可以随时访问变体记录中的所有变体字段。

为了实现您正在寻找的可访问性控制,您需要使用属性并进行运行时检查以控制可访问性。

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;

答案 1 :(得分:3)

即使我听说原版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,以使用属性并进行运行时检查,则更为合理。

答案 2 :(得分:-3)

给出的示例不是变体记录,它始终包含所有字段。

真正的变体记录具有共享相同内存的变体。您只需使用“case discriminator:DiscType of .....”语法,无需单独的字段来告诉您哪个变体处于活动状态。