Delphi - 记录带有变体部分

8
我希望有一个能够表现出“多态”行为的记录(结构)。它将具有几个在所有情况下使用的字段,并且我只想在需要时使用其他字段。我知道可以通过在记录中声明变体部分来实现这一点。我不知道在设计时间是否可能仅访问我需要的元素。为了更具体,看下面的例子。
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个回答

9

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

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

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;

2
这是完全正确的,但在这种情况下,我宁愿使用类而不是记录。它将允许添加继承特性,在这里是有意义的(例如,IsEnable属性通常应在父级别处理,并在子级之间共享)。 - Arnaud Bouchez

3
即使我听说原始的Niklaus Wirth Pascal定义应该按照您的期望工作,但我在Delphi中没有看到这样的行为,从其祖先Turbo Pascal 2.0开始。快速查看FreePascal表明它的行为也是相同的。如Delphi文档所述:
您可以随时读取或写入任何变量的任何字段;但是,如果您先写入一个变量的字段,然后再写入另一个变量的字段,则可能会覆盖自己的数据。标签(如果有)在记录的非变体部分中作为额外的字段(类型为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 .....”语法,无需单独的字段告诉您哪个变体处于活动状态。


这是一个变体记录。它的情况使它成为这样。 - David Heffernan
你在谈论“绝对”变量,这是另一回事。David是正确的,这是一个变体记录。 - Fabricio Araujo
它并不包含所有字段,而是在case之后同时访问所有部分,并且它们共享同一内存。因此,它类似于绝对变量,但是:它更加结构化;你有标签变量;可能,内存对齐略有不同。 - Serhii Kheilyk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接