Myslím, že celkem nedoceněnou vlastností je přetěžovaní operátorů u datové struktury record. Z cvičných důvodů ukáži jak např. emulovat 8bit string za pomocí TBytes.
Operátory a jejich syntaxe je popsaná v helpu, např. Operator Overloading.
Pro začátek si ujasněme co je TBytes.
TBytes = TArray<Byte>
TBytes je preferovaný způsob pro práci s daty v paměti (dříve se pro to hodně používal např. PChar, Pointer atd). Všimněte si, že i např. TBookmark je nyní deklarován jako TBytes. Cílem je nejen větší typová bezpečnost.
unit uString8;
interface
uses
System.SysUtils;
type
TString8 = record
private
FValue: TBytes;
procedure SetValue(const Value: TBytes);
public
property Value: TBytes read FValue write SetValue;
class operator Add (a, b: TString8): TString8;
class operator Implicit (n: TString8): TBytes;
class operator Implicit (s: UnicodeString): TString8;
class operator Implicit (n: TString8): UnicodeString;
end;
function Length(s8:TString8):Integer; overload;
implementation
{ TString }
function Length(s8:TString8):Integer;
begin
Result := System.Length(s8.Value);
end;
class operator TString8.Add(a, b: TString8): TString8;
begin
SetLength(Result.FValue, Length(a) + Length(b));
move(a.Value[0], Result.Value[0], Length(a));
move(b.Value[0], Result.Value[Length(a)], Length(b));
end;
class operator TString8.Implicit(n: TString8): TBytes;
begin
SetLength(Result, Length(n));
move(n.Value[0], Result[0], Length(n));
end;
class operator TString8.Implicit(s: UnicodeString): TString8;
begin
Result.FValue := BytesOf(s);
end;
class operator TString8.Implicit(n: TString8): UnicodeString;
begin
Result := StringOf(n);
end;
procedure TString8.SetValue(const Value: TBytes);
begin
FValue := Value;
end;
end.
Deklarován je nyní typ TString8, který je interně postaven na TBytes a definuje některé operace jako přetypování z a na některé typy a navíc je implementována operace sčítání (jako u normálních řetezců).
Díky tomu lze napsat např.
var
s8:TString8;
s: string;
function readTest:TString8;
begin
Result := 'Hello';
end;
begin
s8 := 'Radek';
writeln(Length(s8));
s8 := s8 + ' delphi.cz';
s := s8;
writeln(s);
s := readTest;
writeln(s);
BytesOf a StringOf jsou funkce z RTL, které provádí konverzi mezi unicodestring a TBytes.
Není to dokonalé. Bohužel jsem nenašel způsob jak napsat přímo writeln(Length(s8)). Nějaký nápad?
Update: Pepák navrh overload Length a to je způsob.