I'm having problems adding my own TCollectionItem
classes (inherited from TCollectionItem
) within the same TOwnedCollection
.
I referred to Indy's IdMessageParts.pas
for TIdMessagePart
as recommended. So I must be missing something as I get a "Invalid class type" error when adding TMyItem2
.
I would like MyItems: TOwnedCollection
to be able to store TMyItem
, TMyItem2
, TMyItem3
. But I get an "Invalid typecast" error when adding TMyItem2
and TMyItem3
(only TMyItem
can be accepted).
Did I miss something?
TMyItem = class(TCollectionItem)
private
FLabelName: string;
public
constructor Create(Collection: TCollection); override;
destructor Destroy; override;
published
property LabelName: string read FLabelName write FLabelName;
end;
TMyItem2 = class(TMyItem)
private
FCaption: string;
published
property Caption: string read FCaption write FCaption;
end;
TMyItem3 = class(TMyItem)
private
FCaption3: string;
published
property Caption3: string read FCaption3 write FCaption3;
end;
TMyItems = class(TOwnedCollection)
private
function GetMyItem(aIndex: Integer): TMyItem;
protected
constructor Create(aOwner: TAsapListview);
function GetOwner: TPersistent; override;
public
function Add: TMyItem;
function IndexOf(aFieldName: string): Integer;
function MyItemByFieldName(aFieldName: string): TMyItem;
property Items[aIndex: Integer]: TMyItem read GetMyItem; default;
end;
// NOTE: in idMessageParts.pas the add is defined this way
// which I don't quite understand
{
function TIdMessageParts.Add: TIdMessagePart;
begin
// This helps prevent TIdMessagePart from being added
Result := nil;
end;
}
// this is the calling code
with MyItems.Add do
begin
LabelName := 'test'; // works
end;
// Error of invalid typecast occurred here
with MyItems.Add as TMyItem2 do // typecast error here
begin
LabelName := 'label item2';
Caption := 'caption item2';
end;
with MyItems.Add as TMyItem3 do // typecast error here
begin
LabelName := 'label item2';
Caption := 'caption item2';
Caption3 := 'caption3 item2';
end;
The inherited
TCollection.Add()
method creates an instance of the class type that is specified in theTCollection
constructor. SoAdd()
is useless when dealing with multipleTCollectionItem
-derived classes, since you can't add multiple classes that way.This code:
Works because you told
TMyItems
that its item class type isTMyItem
, so that is whatAdd()
creates.This code:
Fails for the same reason. You told
TMyItems
to createTMyItem
objects, so you can't cast them to your other class types.Indy's
TIdMessageParts
collection overridesAdd()
to dissuade users from usingAdd()
in this manner.To accomplish what you want (and what Indy does), you need to call the
TCollectionItem
constructor instead of usingAdd()
, eg: