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
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;
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.
To jest wariant rekordu. Sprawa czyni tak. –
Mówisz o ** bezwzględnych ** zmiennych, co jest kolejną zupełnie inną rzeczą. David ma rację, to między innymi wariacja. –
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 –
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.
+1. Byłem w 80% pewien, że to jest odpowiedź ... – RBA
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). –