Pourquoi les variables sont déclarées comme TStrings
et créées comme TStringList
?
par exemple: le var sl
est déclaré comme TStrings
mais créé comme TStringList
var
sl : TStrings;
begin
sl := TStringList.Create;
// add string values...
sl.Add( 'Delphi' );
sl.Add( '2.01' );
// get string value using its index
// sl.Strings( 0 ) will return
// 'Delphi'
MessageDlg(
sl.Strings[ 0 ],
mtInformation, [mbOk], 0 );
sl.Free;
end;
À mon avis, c'est plutôt inutile, mais complètement inoffensif. Vous pourriez parfaitement déclarer que sl
est TStringList
et je le ferais toujours de cette façon. Pour un lecteur du code, cela rend la liste des variables locales plus facile à comprendre.
Dans ce code, sl
se voit toujours attribuer une instance TStringList
et il n'y a donc rien à gagner à déclarer sl
pour avoir le type de classe de base TStrings
. Cependant, si vous aviez du code qui affectait une variété de différents types de descendants TStrings
à la variable, alors il serait logique de la déclarer comme TStrings
.
Les situations où vous pouvez déclarer une variable de type TStrings
sont généralement lorsque le code ne crée pas explicitement l'instance. Par exemple, une méthode utilitaire qui a reçu une liste de chaînes en tant que paramètre serait plus utile si elle acceptait un TStrings
car alors tout descendant pourrait lui être transmis. Voici un exemple simple:
procedure PrintToStdOut(Strings: TStrings);
var
Item: string;
begin
for Item in Strings do
Writeln(Item);
end;
Il est clair que cela est beaucoup plus utile lorsque le paramètre est déclaré TStrings
plutôt que TStringList
.
Cependant, le code dans la question n'est pas de cette nature et je pense qu'il serait toujours si légèrement amélioré si sl
était déclaré de type TStringList
.
TStrings
est un type abstrait qui n'a pas toutes les méthodes implémentées.
TStringList
est un descendant de TStrings
et implémente toutes les fonctions. Dans votre code, vous pouvez également déclarer votre variable comme TStringList
.
Cependant par ex. sur les définitions de fonction, il est logique d'accepter un paramètre TStrings
au lieu d'un TStringList
:
procedure doSomething(lst: TStrings);
Cela permet à la fonction de fonctionner avec toutes les implémentations de TStrings
, pas seulement TStringList
.
Parce que de cette façon, vous pourriez mettre un autre descendant TStrings
dans la variable SL
(je l'appellerais probablement Strings
, pas SL
).
Dans votre cas, c'est théorique, car la logique autour de SL
contient la création d'un TStringList
et aucune affectation externe ou analyse de paramètre.
Mais si jamais vous séparez la logique de l'affectation, vous pouvez alors utiliser n'importe quel descendant TStrings
.
Par exemple, un TMemoy.Lines
, TListBox.Items
, TComboBox.Items
, etc.
De l'extérieur, il semble qu'ils soient TStrings
, mais en interne ils n'utilisent pas un TStringList
mais leur propre descendant.
Quelques exemples de classes qui descendent de TStrings
:
source\DUnit\Contrib\DUnitWizard\Source\DelphiExperts\Common\XP_OTAEditorUtils.pas:
TXPEditorStrings = class(TStrings)
source\fmx\FMX.ListBox.pas:
TListBoxStrings = class(TStrings)
source\fmx\FMX.Memo.pas:
TMemoLines = class(TStrings)
source\rtl\common\System.Classes.pas:
TStringList = class(TStrings)
source\vcl\Vcl.ComCtrls.pas:
TTabStrings = class(TStrings)
TTreeStrings = class(TStrings)
TRichEditStrings = class(TStrings)
source\vcl\Vcl.ExtCtrls.pas:
TPageAccess = class(TStrings)
THeaderStrings = class(TStrings)
source\vcl\Vcl.Grids.pas:
TStringGridStrings = class(TStrings)
TStringSparseList = class(TStrings)
source\vcl\Vcl.Outline.pas:
TOutlineStrings = class(TStrings)
source\vcl\Vcl.StdCtrls.pas:
TCustomComboBoxStrings = class(TStrings)
TMemoStrings = class(TStrings)
TListBoxStrings = class(TStrings)
source\vcl\Vcl.TabNotBk.pas:
TTabPageAccess = class(TStrings)
un TStringList est une implémentation concrète de la classe abstraite TStrings