TStrings的问题 (100分)

  • 主题发起人 主题发起人 looyo
  • 开始时间 开始时间
L

looyo

Unregistered / Unconfirmed
GUEST, unregistred user!
TStrings.Append()是虚拟的方法,执行会报错
Tmemo.lines的类型也是TStrings,但是Tmemo.lines.Append()可以执行
例如
var strs:TStrings

strs:=TStrings.create;
strs.Append('hello world');//这句就会报抽象方法错误
但是
var memo1:Tmemo;

memo1:=Tmemo.create;
memo1.Lines.Append('Hello ');//这句就可以正常执行
[red]为什么类型一样,却有两种结果。[/red]


[red]请注意我要问为什么,而不是找解决方法[/red]
------------------------------
我的MSN&Email:Looyo@163.com
欢迎一起讨论。
 
var strs:TStrings

strs:=TStringList.create;
就可以了
 
strs:=TStringList.Create;

这样就OK了
 
strs:=TStrings.create;
改为:
strs:=TStringList.create
OK!
 
TStrings是个含有纯虚(abstract)函数的类,不能直接使用,可以通过他来使用其它实现了它的纯虚(abstract)函数的类如TStringList,ThashStringList。TStream,TDataSet也是如此。
 
改为:
strs:=TStringList.create

搞定
 
因为Tstrings是一个抽象类。
其不能被实例化。
只有其child类才能够被实例化,并使用其方法。
 
strs:=TStringList.Create;
 
Delphi中,一个类的类型变量不会为对象提供存储,而只是在内存中为对象提供一个指针或引用。在使用对象之前,必须创建一个新的实例或将一个现有的实例分配给变量,以此来为器分配内存。所以在声明过变量后var strs:TStrings,还要创建实例strs:=TStrings.create;
 
因为
procedure TStrings.Append(const S: string);
begin
Add(S);
end;
function TStrings.Add(const S: string): Integer;
begin
Result := GetCount;
Insert(Result, S);
end;

procedure Insert(Index: Integer
const S: string)
virtual
abstract;

insert在tstrings的子类中实现.
 
这是一个与多态相关的问题。

来自:looyo, 时间:2004-3-30 17:04:00, ID:2530138
...
var strs:TStrings

strs:=TStrings.create;
strs.Append('hello world');//这句就会报抽象方法错误
但是
var memo1:Tmemo;

memo1:=Tmemo.create;
memo1.Lines.Append('Hello ');//这句就可以正常执行
[red]为什么类型一样,却有两种结果。[/red]

strs是Tstrings(抽象类,其中有很多的抽象方法如insert等)类型的引用,它可以指向(或引用)其派生类的对象。抽象方法只是提供了接口,而没有提供实现,其实现有其派生类来实现,‘strs.append’用法是正确的,这也是多态性的一个体现(用同样的调用方法让不同的派生类的对象进行各自的操作), 错误是的strs 没有指向一个对象。你用TStrings.create来创建对象是不行的。因为是没有抽象类的对象!
不能直接strs:=TStrings.create创建对象;//这本来就是一个错误的用法。不能创建抽象类的对象(实例)!!
memo1.Lines也是定义的是Tstrings 类型的引用,但它指向的是一个TMemoStrings类型的对象。请看VCL中的代码:
property Lines: TStrings read FLines write SetLines;
constructor TCustomMemo.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Width := 185;
Height := 89;
AutoSize := False;
FWordWrap := True;
FWantReturns := True;
FLines := TMemoStrings.Create
//注意这一行
TMemoStrings(FLines).Memo := Self;
end;

TMemoStrings中有对insert 方法的实现
procedure TMemoStrings.Insert(Index: Integer
const S: string);
var
SelStart, LineLen: Integer;
Line: string;
begin
if Index >= 0 then
begin
SelStart := SendMessage(Memo.Handle, EM_LINEINDEX, Index, 0);
if SelStart >= 0 then Line := S + #13#10 else
begin
SelStart := SendMessage(Memo.Handle, EM_LINEINDEX, Index - 1, 0);
if SelStart < 0 then Exit;
LineLen := SendMessage(Memo.Handle, EM_LINELENGTH, SelStart, 0);
if LineLen = 0 then Exit;
Inc(SelStart, LineLen);
Line := #13#10 + s;
end;
SendMessage(Memo.Handle, EM_SETSEL, SelStart, SelStart);
SendMessage(Memo.Handle, EM_REPLACESEL, 0, Longint(PChar(Line)));
end;
end;

故可以append操作

 
抽象的基类 (非抽象)派生类
Tstrings ——|-TStringList ---一般我们自己用的字符串列表
|-TMemoStrings ---TMemo.Lines的实际对象的类型
|-TListBoxStrings ---TlistBox.items的实际对象的类型
|-TCustomComboBoxStrings ---TComboBox.items的实际对象的类型
...
同样的接口使得我使用这些控件的字符串列表感觉没有差别,我想这就是多态给我带来的好处!!!!也是VCL的设计的一个亮点
当然如果你调用其派生独有的东西,强制转换一下就ok了。


 
类似的架构设计在VCL还有很多地方用到,VCL/RTL博大精深,本人才疏学浅,只是略知一些皮毛,欢迎有志人事共同探讨!
QQ:122646527
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
915
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部