2011-10-26 84 views
6

我想创建一个具有'多态'配置的记录(结构)。它会在所有情况下使用几个字段,并且我只在需要时才使用其他字段。我知道我可以通过在记录中声明的变体部分来完成此操作。我不知道在设计时是否有可能只能访问我需要的元素。更具体的看下面的例子:德尔福 - 不同部分的记录

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. 

这可能吗?

回答

7

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

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

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

+1。我80%确定这是答案... – RBA

+2

这是完全正确的,但在这种情况下,我宁愿使用类而不是记录。它将允许添加继承功能,这在此处是有意义的(例如,IsEnable属性通常在父级别处理,并在儿童之间共享)。 –

-3

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

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

+0

这是一个变种记录。案件如此。 –

+0

你在谈论**绝对**变量,这是另一个完全不同的东西。大卫说得对,这是一个变种记录。 –

+0

它不包含所有的字段,它可以在同一时间访问'case'之后的所有部分,并且它们都共享相同的内存。所以它类似于**绝对**变量,除了:它更结构化;你有标签变量;并且,可能的,内存对齐有点不同 –

3

即使我听说原来的Niklaus Wirth的帕斯卡定义都应该如你期望的那样工作,但我从德尔菲的祖先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的代码编辑器的一些支持。更多有用的,虽然是,这将是得多容易多修改和支持更高版本。

但是,如果您需要快速切换记录VA运行时的riable值,@David Heffernan's variant,使用属性并进行运行时检查,更合理。