Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

TStrings property : Abstract error

974 views
Skip to first unread message

Jens Dein

unread,
Nov 11, 1997, 3:00:00 AM11/11/97
to

Hi,

I have just created a property og type TStrings, and I thought this could
cause no problems at all, but when I access it at designtime I get this
error : Abstract error

Why?

It has both read and write declarations, just like the SQL prpperty on
TQuery.

Does anybody have any idea what I am doing wrong?

Gerald Nunn

unread,
Nov 11, 1997, 3:00:00 AM11/11/97
to

Use TStrings as the property, but when you actually create it, create a
TStringList. For example

property MyList: TStrings read GetList write SetList

.
.
.
implementation
.
.
.
Constructor MyObject.Create;
Begin
inherited Create;
FMyList:=TStringList.Create; {NOT TStrings here}
End;

The TStrings is an abstract class whose methods you cannot use.

Gerald

In article <64abc9$rd...@forums.borland.com>, "Jens Dein"

----------------------------------------------
Gerald Nunn, Toronto, Canada
GExperts, 15 free add-in experts for Delphi
http://www.amano-blick.com/~gnunn/GExperts.htm
----------------------------------------------

Rick Rogers [TeamB]

unread,
Nov 11, 1997, 3:00:00 AM11/11/97
to

In article <64abc9$rd...@forums.borland.com>, Jens Dein wrote:
> I have just created a property og type TStrings

TStrings *is* an abstract class. Here's a heavily commented class
demonstrates the reason why you would want to declare a property as the
abstract TStrings class, but instantiate it as a non-abstract TStrings
descendant:

TBrianClass = class(TObject)
private
FItems : TStrings; { Note: TStrings, not TStringList }
procedure SetItems(Value: TStrings);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property Items: TStrings read FItems write SetItems;
end;

constructor TBrianClass.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
{
TStrings is an ABSTRACT class, which means it has methods
which are declared "virtual; abstract;". Abstract methods
are not implemented, and MUST be implemented by descendants.
The TStrings methods which are abstract relate to the actual
storage mechanism for the string and object values.

Because TStrings is abstract, we MUST NOT instantiate it.
Any statement such as FItems := TStrings.Create; will result
in a compiler or run-time error (depending on the version of
Delphi) because the abstract methods have not been
implemented.

We declared our property a TStrings, however, because we
would like the property to be type-compatible with any
TStrings descendant. Remember that descendant classes are
always type-compatible with their ancestors. TStringList is
just one example of a TStrings descendant; the VCL includes
many others, such a TMemoStrings and TListBoxStrings.

The reason the VCL includes the TStrings abstract class is
to provide a common interface to a list of strings, even
though the underlying storage mechanism of those strings is
different from class to class. So TStringList maintains
strings in a TList structure, while TMemoStrings uses the
Windows API to store the strings right in the Microsoft
Windows common memo control.

Since we cannot instantiate the TStrings class, the next
statement creates a TStringList instance and assigns it to
FItems. This is OK because descendants are type-compatible
with ancestors. This technique gives us the best of both
worlds -- the property uses the generic and abstract
TStrings interface, and the internal class field uses the
TStringList class, which manages the string/object storage. }

FItems := TStringList.Create;

end;

destructor TBrianClass.Destroy; override;
begin
FItems.Free;
inherited Destroy;
end;

procedure TBrianClass.SetItems(Value: TStrings);
begin
{
The Value parameter can be any TStrings descendant,
including TStringList, TMemoStrings, TListBox strings,
etc.

The Assign method is a special TPersistent method which
by default does nothing but raise an exception. This
method is virtual, which means descendant classes can
override it to provide appropriate "copy semantics" for
the class.

In this case, the TStrings ancestor class overrides Assign
and loops through the strings, copying the string/object
pairs from the source TStrings to the destination TStrings.
It doesn't matter what TStrings descendant the source or
destination are, because the Assign method uses the base
interface methods which are implemented in the ancestor
itself, TStrings. This is another example of why abstract
classes are great.

So in this case, you could assign any TStrings descendant
to the Items property of a TBrianClass instance like this:

BrianClass.Items := Memo1.Lines;
BrianClass.Items := ListBox1.Items;
BrianClass.Items := MyStringList;

&etc.
}
FItems.Assign(Value);
end;

--
Rick Rogers (TeamB) | Fenestra Technologies

0 new messages