Delphi Record Helpers dla zestawów i innych prostych typów

Zrozumienie pomocników klasy (i nagrywania) Delphi wprowadza funkcję języka Delphi pozwalającą rozszerzyć definicję klasy lub typu rekordu poprzez dodanie funkcji i procedur (metod) do istniejących klas i rekordów bez dziedzictwo.

W wersji XE3 Delphi pomocnicy w nagrywaniu stali się bardziej wydajni, pozwalając na rozszerzenie prostych typów Delphi, takich jak ciągi, liczby całkowite, wyliczenia, zbiory i tym podobne.

System. Jednostka SysUtils, z Delphi XE3, implementuje rekord o nazwie „TStringHelper”, który w rzeczywistości jest pomocnikiem rekordów dla łańcuchów.

Za pomocą Delphi XE3 możesz skompilować i użyć następnego kodu:

var
s: string; zaczynać
s: = „Delphi XE3”; s. Zamień („XE3”, „rules”, []). ToUpper; koniec; 

Aby było to możliwe, w Delphi utworzono nowy konstrukt „pomocnik rekordów dla [prostego typu]”. W przypadku ciągów jest to „typ TStringHelper = pomocnik rekordu dla ciągu”. Nazwa określa „pomocnika rekordu”, ale nie chodzi o rozszerzenie dokumentacja - raczej o rozszerzaniu prostych typów, takich jak ciągi, liczby całkowite i tym podobne.

instagram viewer

W systemie i systemie. SysUtils istnieją inne predefiniowane pomocniki zapisu dla prostych typów, w tym: TSingleHelper, TDoubleHelper, TExtendedHelper, TGuidHelper (i kilka innych). Możesz uzyskać od nazwy, jaki prosty typ rozszerza pomocnik.

Istnieje również kilka przydatnych pomocników typu open source, takich jak TDateTimeHelper.

Wyliczenia? Pomocnik do wyliczeń?

wyliczenia
zestawy

Wyliczenia i zestawy traktowane jako typy proste mogą być teraz (w XE3 i późniejszych wersjach) rozszerzane o funkcjonalność, jaką może mieć typ rekordu: funkcje, procedury i tym podobne.

Oto proste wyliczenie („TDay”) i pomocnik rekordów:

rodzaj
TDay = (poniedziałek = 0, wtorek, środa, czwartek, piątek, sobota, niedziela); TDayHelper = pomocnik dla TDay. funkcjonować AsByte: bajt; funkcjonować ToString: strunowy; koniec; 
funkcjonować TDayHelper. AsByte: bajt; zaczynać
wynik: = bajt (jaźń); koniec; funkcjonować TDayHelper. ToString: strunowy; zaczynaćwalizka samego siebie z
Poniedziałek: wynik: = „poniedziałek”; Wtorek: wynik: = „wtorek”; Środa: wynik: = „środa”; Czwartek: wynik: = „czwartek”; Piątek: wynik: = „piątek”; Sobota: wynik: = „sobota”; Niedziela: wynik: = „niedziela”; koniec; koniec; 
var
aDay: TDay; s: string; zaczynać
aDay: = TDay. Poniedziałek; s: = aDay. ToString. Obniżyć; koniec; 
przekonwertować wyliczenie Delphi na reprezentację ciągu

Zestawy? Pomocnik dla zestawów?

TDays = zestaw TDay; 
var
dni: TD; s: string; zaczynać
dni: = [poniedziałek.. Środa]; dni: = dni + [niedziela]; koniec; 

ALE, jak WIELKIE byłoby, aby móc:

var
dni: TD; b: boolean; zaczynaćdni: = [poniedziałek, wtorek] b: = dni. Przecięcie ([poniedziałek, czwartek]). IsEmpty;
rodzaj
TDaysHelper = pomocnik dla TDays. funkcjonować Krzyżować(const dni: TD): TD; funkcjonować IsEmpty: boolean; koniec;... funkcjonować TDaysHelper. Krzyżować(const dni: TD): TD; zaczynać
wynik: = jaźń * dni; koniec; funkcjonować TDaysHelper. IsEmpty: boolean; zaczynać
wynik: = jaźń = []; koniec; 

Dla każdego typu zestawu zbudowanego wokół wyliczenia trzeba mieć osobnego pomocnika, ponieważ niestety wyliczenia i zestawy nie idą w parze rodzaje ogólne i typy ogólne.

Oznacza to, że nie można skompilować następujących elementów:

// ŻADNY KOMPILEK PODOBNY!
TGenericSet = zestaw ; 
TEnum Prosty rodzajowy przykład Enum

Rekord pomocnika dla zestawu bajtów!

rodzaj
TByteSet = zestaw Bajt; TByteSetHelper = pomocnik dla TByteSet. 

W definicji TByteSetHelper możemy mieć następujące elementy:

publicznyprocedura Jasny; procedura Zawierać(const wartość: bajt); przeciążać; inline; procedura Zawierać(const wartości: TByteSet); przeciążać; inline; procedura Wykluczać(const wartość: bajt); przeciążać; inline; procedura Wykluczać(const wartości: TByteSet); przeciążać; inline; funkcjonować Krzyżować(const wartości: TByteSet): TByteSet; inline; funkcjonować IsEmpty: boolean; inline; funkcjonować Obejmuje (const wartość: Byte): boolean; przeciążać; inline;funkcjonować Obejmuje (const wartości: TByteSet): boolean; przeciążać; inline;funkcjonować IsSuperSet (const wartości: TByteSet): boolean; inline; funkcjonować IsSubSet (const wartości: TByteSet): boolean; inline; funkcjonować Równa się(const wartości: TByteSet): boolean; inline; funkcjonować ToString: strunowy; inline; koniec; 
{TByteSetHelper}procedura TByteSetHelper. Uwzględnij (stała wartość: bajt); zaczynać
System. Uwzględnij (jaźń, wartość); koniec; procedura TByteSetHelper. Wyklucz (stała wartość: bajt); zaczynać
System. Wyklucz (jaźń, wartość); koniec; procedura TByteSetHelper. Jasny; zaczynać
self: = []; koniec; funkcjonować TByteSetHelper. Równa się (wartości stałe: TByteSet): boolean; zaczynać
wynik: = jaźń = wartości; koniec; procedura TByteSetHelper. Wyklucz (wartości stałe: TByteSet); zaczynać
self: = self - wartości; koniec; procedura TByteSetHelper. Include (const wartości: TByteSet); zaczynać
self: = self + wartości; koniec; funkcjonować TByteSetHelper. Obejmuje (const wartości: TByteSet): boolean; zaczynać
wynik: = IsSuperSet (wartości); koniec; funkcjonować TByteSetHelper. Przecięcie (stałe wartości: TByteSet): TByteSet; zaczynać
wynik: = wartości własne *; koniec; funkcjonować TByteSetHelper. Obejmuje (const wartość: Byte): boolean; zaczynać
wynik: = wartość w sobie; koniec; funkcjonować TByteSetHelper. IsEmpty: boolean; zaczynać
wynik: = jaźń = []; koniec; funkcjonować TByteSetHelper. IsSubSet (const wartości: TByteSet): boolean; zaczynać
wynik: = samo <= wartości; koniec; funkcjonować TByteSetHelper. IsSuperSet (const wartości: TByteSet): boolean; zaczynać
wynik: = jaźń> = wartości; koniec; funkcjonować TByteSetHelper. ToString: string; var
b: bajt; zaczynaćdla b w samego siebie robić
wynik: = wynik + IntToStr (b) + ','; wynik: = Kopiuj (wynik, 1, -2 + długość (wynik)); koniec; 
var
daysAsByteSet: TByteSet; zaczynać
daysAsByteSet. Jasny; daysAsByteSet. Uwzględnij (poniedziałek. AsByte); daysAsByteSet. Uwzględnij (liczba całkowita (sobota); daysAsByteSet. Uwzględnij (bajt (TDay. Wtorek)); daysAsByteSet. Uwzględnij (liczba całkowita (TDay. Środa)); daysAsByteSet. Uwzględnij (liczba całkowita (TDay. Środa)); // 2. raz - bez sensu. daysAsByteSet. Wyklucz (TDay. Wtorek. AsByte); ShowMessage (daysAsByteSet. ToString); ShowMessage (BoolToStr (daysAsByteSet. IsSuperSet ([poniedziałek. AsByte, sobota. AsByte]), true)); koniec; 

Jest ale :(

Zauważ, że TByteSet akceptuje wartości bajtów - i każda taka wartość zostałaby tutaj zaakceptowana. TByteSetHelper, jak zaimplementowano powyżej, nie jest typu ścisłego wyliczenia (tzn. Można go podać wartością inną niż TDay)... ale tak długo jak jestem świadomy... to działa dla mnie.