2011-10-26 93 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,使用屬性並進行運行時檢查,更合理。