Подтвердить что ты не робот

Почему переменные объявлены как TStrings и созданы как TStringList?

Почему переменные объявляются как TStrings и создаются как TStringList?

например: var sl объявлен как TStrings, но создан как 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;
4b9b3361

Ответ 1

На мой взгляд, это довольно бессмысленно, хотя и совершенно безвредно. Вы могли бы прекрасно заявить sl как TStringList, и я всегда буду делать это именно так. Для читателя кода он облегчает понимание списка локальных переменных.

В этом коде sl всегда присваивается экземпляр TStringList, поэтому нет ничего, что можно было бы объявить sl, чтобы иметь тип базового класса TStrings. Однако, если бы у вас был код, который присваивал переменной различные типы потомков TStrings, тогда было бы разумно объявить его как TStrings.

Ситуации, когда вы могли бы объявить переменную типа TStrings, обычно были бы, когда код явно не создавал экземпляр. Например, полезный метод, получивший строковый список в качестве параметра, был бы более полезен, если бы он принял TStrings, так как тогда любой потомок мог быть передан ему. Вот простой пример:

procedure PrintToStdOut(Strings: TStrings);
var
  Item: string;
begin
  for Item in Strings do
    Writeln(Item);
end;

Очевидно, что это гораздо более полезная функция, если объявлен параметр TStrings, а не TStringList.

Однако код в этом вопросе не имеет такого характера, и я считаю, что он будет настолько мягко улучшен, если объявлен sl типа TStringList.

Ответ 2

TStrings - абстрактный тип, который не имеет всех реализованных методов.

TStringList является потомком TStrings и реализует все функции. В вашем коде вы также можете объявить свою переменную как TStringList.

Однако, например, на определениях функций имеет смысл принять параметр TStrings вместо TStringList:

procedure doSomething(lst: TStrings);

Это позволяет функции работать со всеми реализациями TStrings, а не только TStringList.

Ответ 3

Таким образом, вы можете поместить другого TStrings потомка в переменную SL (я бы назвал это Strings, а не SL).

В вашем случае, это спорный вопрос, так как логика вокруг SL содержит создание TStringList и нет внешнего назначения или параметр синтаксического анализа.

Но если вы когда-либо отделили логику от назначения, тогда вы могли бы использовать любой потомок TStrings.

Например, a TMemoy.Lines, TListBox.Items, TComboBox.Items и т.д.
Снаружи это выглядит как TStrings, но внутри они не используют TStringList, а свой собственный потомок.

Несколько примеров классов, начинающихся с 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)

Ответ 4

a TStringList - это конкретная реализация абстрактного класса TStrings