代码如下 sTableNames := TStrings.Create;
Screen.Cursor:=crHourGlass;
SetDbPath.SetConnection(ADOC);
ADOQ.Connection := ADOC;
ADOC.GetTableNames(sTableNames,False); //这里产生了一个Abstract Error 抽象类型错误?
for i := 0 to sTableNames.Count -1 do
Begin
ADOQ.SQL.Text := 'Drop Table ' + sTableNames[i];
ADOQ.ExecSQL;
end;明明GetTableNames的原型是
GetTableNames(List: TStrings;SystemTables: Boolean);为什么我用TStrings做参数却不行呢??非得要用TStringList做参数吗?虽然TStringList是它的一个子类,
难道TStrings是抽象类(好象类都是抽象的)问题是如果把Table给TlistBox的Item又不会报错,Item可是一个TStrings对象啊
Screen.Cursor:=crHourGlass;
SetDbPath.SetConnection(ADOC);
ADOQ.Connection := ADOC;
ADOC.GetTableNames(sTableNames,False); //这里产生了一个Abstract Error 抽象类型错误?
for i := 0 to sTableNames.Count -1 do
Begin
ADOQ.SQL.Text := 'Drop Table ' + sTableNames[i];
ADOQ.ExecSQL;
end;明明GetTableNames的原型是
GetTableNames(List: TStrings;SystemTables: Boolean);为什么我用TStrings做参数却不行呢??非得要用TStringList做参数吗?虽然TStringList是它的一个子类,
难道TStrings是抽象类(好象类都是抽象的)问题是如果把Table给TlistBox的Item又不会报错,Item可是一个TStrings对象啊
function Get(Index: Integer): string; virtual; abstract;
function GetCount: Integer; virtual; abstract;
procedure Clear; virtual; abstract;
procedure Delete(Index: Integer); virtual; abstract;
procedure Insert(Index: Integer; const S: string); virtual; abstract;
而你的GetTableNames(List: TStrings;SystemTables: Boolean);函数实现是这样的。procedure TADOConnection.GetTableNames(List: TStrings;
SystemTables: Boolean);
var
TypeField,
NameField: TField;
TableType: string;
DataSet: TADODataSet;
begin
CheckActive;
DataSet := TADODataSet.Create(nil);
try
OpenSchema(siTables, EmptyParam, EmptyParam, DataSet);
TypeField := DataSet.FieldByName('TABLE_TYPE'); { do not localize }
NameField := DataSet.FieldByName('TABLE_NAME'); { do not localize }
List.BeginUpdate;
try
List.Clear;
while not DataSet.EOF do
begin
TableType := TypeField.AsString;
if (TableType = 'TABLE') or (TableType = 'VIEW') or { do not localize }
(SystemTables and (TableType = 'SYSTEM TABLE')) then { do not localize }
List.Add(NameField.AsString);
DataSet.Next;
end;
finally
List.EndUpdate;
end;
finally
DataSet.Free;
end;
end;//这里面使用了抽象方法,而你实例化的是一个TStrings的抽象类,它本身并没有实现List.Clear;之类的方法,当然会出错
其中
GetTableNames(List: TStrings;SystemTables: Boolean);
它的List: TStrings 参数的约定并不是一定要用TStrings类型的对象去做参数,而是指从TStrings派伸出来的实现了抽象方法的其他类对象都可以做为参数。
List更多的是做为引用这些对象的意思。因为一个祖先类的变量可以引用它的子类的对象。
这是很简单的道理,在D中,
如:我说的肯定是比如啊,呵呵,一个函数用TEDIT不会说你用somefun(somevar:TEDIT;……),而用somefun(somevar:Twincontrol;……)
hottey(点亮心灵)(基础补习中)
qizhanfeng(glacier)
private
FAutoComplete: Boolean;
FCount: Integer;
FItems: TStrings;
.....
property Items: TStrings read FItems write SetItems;
.........procedure TCustomListBox.SetItems(Value: TStrings);
begin
if Style in [lbVirtual, lbVirtualOwnerDraw] then
case Style of
lbVirtual: Style := lbStandard;
lbVirtualOwnerDraw: Style := lbOwnerDrawFixed;
end;
Items.Assign(Value);
end;
既然TStrings的某些方法是抽象的,需要在子类里面实现的,Delphi中是允许对抽象类进行实例化的,这一点和C++以及Java是不同的,我们声明一个TString的对象时,还是可以访问其实现了的普通方法的,只要你不访问它的抽象方法,就不会产生
Abstract Error 错误。毕竟Tstring也定义并实现了一些普通方法,因此FItems: TStrings; 时,即使是用TStrings来构造FItems 也不会出现问题,除非你使用TStrings 的抽象方法时才会出现错误,并且大多数情况下我们这么声明FItems: TStrings;并不是为了去用TStrings去构造FItems,更多的是一种对子类实例对象的引用。以此来使FItems 来表现出不同的行为。