为什么变量被声明为TStrings并创建为TStringList?

Fab*_*ale 38 delphi 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;
Run Code Online (Sandbox Code Playgroud)

Chr*_*ris 36

TStrings 是一个没有实现所有方法的抽象类型.

TStringListTStrings所有函数的后代并实现它们.在您的代码中,您也可以将变量声明为TStringList.

但是,例如在函数定义上接受TStrings参数而不是TStringList:

procedure doSomething(lst: TStrings);
Run Code Online (Sandbox Code Playgroud)

这使得与所有实现工作的功能TStrings不仅,TStringList.


Dav*_*nan 29

在我看来,这是毫无意义的,尽管完全无害.你可以非常清楚宣布slTStringList和我总是这样做的.对于代码的读者,它使局部变量列表更容易理解.

在这段代码sl中总是分配一个TStringList实例,因此声明sl拥有基类类型没有任何好处TStrings.但是,如果您的代码TStrings为变量分配了各种不同类型的后代,那么将其声明为有意义TStrings.

您可能将变量声明为类型的TStrings情况通常是代码未显式创建实例的情况.例如,接收字符串列表作为参数的实用程序方法如果接受a则会更有用,TStrings因为任何后代都可以传递给它.这是一个简单的例子:

procedure PrintToStdOut(Strings: TStrings);
var
  Item: string;
begin
  for Item in Strings do
    Writeln(Item);
end;
Run Code Online (Sandbox Code Playgroud)

显然,当声明参数TStrings而不是声明时,这是更有用的TStringList.

然而,问题中的代码并不具有这种性质,我相信如果sl宣布为类型的话,它将会得到如此温和的改进TStringList.

  • 如你所指出的那样(但描述得不太好),这个好设计的原因是它允许你在`PrintToStdOut`中使用任何`TStrings`后代,所以`TStringList`,`Memo1.Lines`,`ListBox1. Items`等工作得非常好.声明它采用`TStringList`意味着最后两次调用将失败. (12认同)

Jer*_*ers 8

因为这样你可以TStringsSL变量中加入另一个后代(我可能会调用它Strings,而不是SL).

在你的情况下,这是没有实际意义,因为周围的逻辑SL包含创建一个TStringList没有外部赋值或参数解析.

但是,如果您将逻辑从分配中分离出来,那么您可以从使用任何TStrings后代中受益.

举例来说,一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)
Run Code Online (Sandbox Code Playgroud)


Pet*_*esh 6

TStringList是抽象TStrings类的具体实现

  • 如果你知道为什么有抽象基类是好的,同样的原因,有时候有一个接口是个好主意.在delphi中,抽象基类是没有引用计数的单继承接口. (3认同)