2011-10-26 10 views
6

Chcę mieć rekord (strukturę) z "polimorficznym" kompendium. Będzie miał kilka pól używanych we wszystkich przypadkach i chcę używać innych pól tylko wtedy, gdy ich potrzebuję. Wiem, że mogę to osiągnąć poprzez części zamienne zadeklarowane w rekordach. Nie wiem, czy jest możliwe, że w czasie projektowania mogę uzyskać dostęp tylko do tych elementów, których potrzebuję. Aby być bardziej szczegółowym, spójrz na przykład poniżej: Czy jest to możliwe?Delphi - rekordy z częściami wariantów

Odpowiedz

7

Wszystkie pola wariantu w rekordzie wariantu są dostępne przez cały czas, niezależnie od wartości znacznika.

Aby osiągnąć pożądaną kontrolę dostępu, konieczne jest użycie właściwości i kontrola czasu działania w celu kontrolowania dostępności.

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. Byłem w 80% pewien, że to jest odpowiedź ... – RBA

+2

Jest to całkowicie poprawne, ale w tym przypadku wolałbym raczej użyć klasy zamiast zapisu. Umożliwi to dodanie funkcji dziedziczenia, która ma tutaj sens (np. Własność IsEnable zazwyczaj jest obsługiwana na poziomie nadrzędnym i współdzielona przez dzieci). –

-3

Podany przykład NIE jest rekordem wariantowym, zawiera wszystkie pola przez cały czas.

Prawdziwy wariant rekordu ma warianty współużytkujące tę samą pamięć. Po prostu używasz składni "discriminator: DiscType of .....", nie ma potrzeby osobnego pola informującego o tym, który wariant jest aktywny.

+0

To jest wariant rekordu. Sprawa czyni tak. –

+0

Mówisz o ** bezwzględnych ** zmiennych, co jest kolejną zupełnie inną rzeczą. David ma rację, to między innymi wariacja. –

+0

Nie zawiera wszystkich pól, zamiast tego daje dostęp do wszystkich części po "przypadku" _ w tym samym czasie_, a wszystkie z nich mają tę samą pamięć. Jest to podobne do ** absolute ** vars, z wyjątkiem: jest bardziej uporządkowane; masz zmienną tag; i, możliwe, wyrównanie pamięci jest nieco inne –

3

Nawet jeśli słyszałem, że według oryginalnej definicji Pascala Niklausa Wirtha wszystko powinno działać zgodnie z oczekiwaniami, nie widziałem takiego zachowania w Delphi, począwszy od jego przodka, Turbo Pascal 2.0. Szybkie spojrzenie na FreePascal pokazało, że its behaviour jest takie samo. Jak wspomniano w: Delphi documentation:

Możesz czytać lub pisać w dowolnym polu dowolnego wariantu w dowolnym momencie; ale jeśli napiszesz do pola w jednym wariancie, a następnie do pola w innym wariancie, możesz nadpisać własne dane. Tag, jeśli istnieje, funkcjonuje jako dodatkowego pola (typu ordinalType) w części będącej wariantem rekord.”

dotycząceTwojego intencji, o ile dobrze zrozumiałem, chciałbym użyć dwóch różnych klas, rodzaj

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; 

w ten sposób można uzyskać pewne wsparcie od edytor kodu IDE nawet przy designtime. bardziej przydatny jest jednak to, że będzie znacznie łatwiejsze do modyfikacji i wsparcie później.

Jednakże, jeśli potrzebujesz szybkiej zmiany rekordu va wartości riable w czasie wykonywania, @David Heffernan's variant, aby używać właściwości i mieć kontrole w czasie wykonywania, jest bardziej uzasadnione.

Powiązane problemy