Enregistrements managés personnalisés
Le type enregistrement de Delphi prend maintenant en charge la finalisation et l'initialisation personnalisées au-delà des opérations par défaut réalisées par le compilateur pour les enregistrements managés (c'est-à-dire les enregistrements ayant des champs dont les types sont gérés par des chaînes de type compilateur). Vous pouvez déclarer un enregistrement avec du code d'initialisation et de finalisation personnalisé indépendamment du type de données de ses champs, et écrire ce code d'initialisation et de finalisation personnalisé. Vous devez pour cela ajouter un constructeur sans paramètres au type d'enregistrement et un destructeur (vous pouvez avoir l'un sans l'autre).
Voici ci-dessous un extrait de code simple :
type
TMyRecord = record
Value: Integer;
constructor Create;
destructor Destroy;
end;
Vous devez écrire le code pour les deux méthodes. La principale différence entre ce nouveau constructeur et ce qui existait auparavant pour les enregistrements se situe au niveau de l'invocation automatique. Lorsque vous écrivez du code similaire au code ci-dessous, vous pouvez invoquer le constructeur par défaut et le destructeur, puis terminer par un bloc try-finally généré par le compilateur pour votre instance d'enregistrement managé.
procedure TForm5.btnMyRecordClick(Sender: TObject);
var
my1: TMyRecord;
begin
Log (my1.Value.ToString);
end;
Par ailleurs, l'extrait de code ci-dessous vous permet d'invoquer explicitement le constructeur par défaut de l'enregistrement.
myrec := TMyRecord.Create;
L'opérateur Assign
Les enregistrements managés personnalisés vous permettent d'exécuter du code personnalisé de façon à assigner un enregistrement à un autre enregistrement. Plutôt que de copier l'ensemble des données, champ par champ, vous pouvez effectuer différentes tâches, garder une copie de certains champs, dupliquer un objet auquel un enregistrement fait référence, ou toute autre opération personnalisée. Le nouvel opérateur est invoqué par la syntaxe :=
mais est défini en tant que Assign :
type
TMyRecord = record
Value: Integer;
class operator Assign (var Dest: TMyRecord; const [ref] Src: TMyRecord);
La définition de l'opérateur doit suivre des règles précises, y compris le fait d'utiliser le premier paramètre comme un paramètre de référence et le second comme un paramètre var
ou const
transmis par référence. Si vous ne procédez pas ainsi, le compilateur enverra des messages d'erreur comme ci-dessous :
[dcc32 Error] E2617 First parameter of Assign operator must be a var parameter of the container type [dcc32 Hint] H2618 Second parameter of Assign operator must be a const[Ref] or var parameter of the container type
L'extrait de code ci-dessous invoque l'opérateur Assign :
var
my1, my2: TMyRecord;
begin
my1.Value := 22;
my2 := my1;
L'opérateur Assign est utilisé conjointement avec des opérations d'assignation comme dans l'exemple ci-dessus, mais aussi si vous utilisez une assignation pour initialiser une variable inline (dans ce cas, le constructeur par défaut n'est pas appelé) :
var my4 := my1;
Constructeur de copie
Lorsque vous transmettez un paramètre d'enregistrement ou que vous souhaitez créer un nouvel enregistrement à partir d'un enregistrement existant, vous pouvez définir un constructeur de copie : un constructeur qui prend un enregistrement du même type que le paramètre. Il peut arriver que vous souhaitiez aussi avoir un constructeur par défaut, vous devez dans ce cas les marquer avec la directive overload :
TMyRecord = record
constructor Create; overload;
constructor Create (const mr: TMyRecord); overload;
Si vous définissez une méthode ou une procédure avec un paramètre valeur normal (non transmis par const
ou var
), il utilisera le constructeur de copie et non un appel d'assignation lorsque vous l'invoquerez :
procedure ProcessRec (mr: TMyRecord);
begin
Log (mr.Value.ToString);
end;
Sachez que le destructeur Destroy sera aussi appelé à la fin de la procédure. Le constructeur de copie peut aussi être invoqué en utilisant la déclaration de variable inline suivante :
var my3 := TMyRecord.Create (my1);