Create an object for a universal list of objects

I'm not sure if this is possible in Delphi. I looked around and could not find the answer (example or invalidity that this is impossible):

I have a generic list class and I want to create an instance of type generic. For instance:

type TTypeA = class(TObject); procedure Test; var MyList: TobjectList<TTypeA>; NewListObject: TTypeA; begin MyList := TObjectList<TTypeA>.Create; NewListObject := MyList.xxx //what to put on the xxx end; 

Is it possible to create a function xxx that creates a new object of type TTypeA?

@jeroen: thanks for the answer below. However, I forgot about the important detail in my question:

I would like this code to work for any other type, so without prior knowledge of type T for TObjectList. I could create the following lists:

 MyList: TObjectList<TCar>; MyList: TObjectList<TBike>; 

Not knowing if MyList contains TCar or TBike (both derived from the same base class and equal constructors), I want to add a new element to MyList.

And with a proposal from Uwe Raabe, I ran into the following problem:

I changed my class to

TMyObjectList<T:class, constructor> = class(TMyBaseObjectList<T>)

where TMyBaseObjectList is defined as

TMyBaseObjectList<T:TMyBaseObject> = class(TObjectList)

Now I get an error: A parameter of type "T" is incompatible with type "T: TMyBaseObject"

+4
source share
5 answers

As you know type, why don't you just write

 NewListObject := TTypeA.Create; MyList.Add(NewListObject); 

That would be a natural way to do here. (I just notified Jeroen a similar answer)

If you want the container to create an object, you must create a descendant class that knows a little about the generic type in order to create an instance. A constructor constraint may help here.

 type TMyObjectList<T:class, constructor> = class(TObjectList<T>) public function NewObject: T; end; function TMyObjectList<T>.NewObject: T; begin result := T.Create; end; 

Note: This will only work if the actual type has a constructor with no parameters named Create.

Refresh . This will help

  TMyObjectList<T:constructor, TMyBaseObject> = class(TObjectList<T>) public function NewObj: T; end; 
+3
source

In xxx put this: TTypeA.Create(...); where ... are the parameters of your create constructor.

0
source

I guess this is not possible. Unless, of course, you have items in your list, in this case you can do:

  NewListObject := MyList[0].ClassType.NewInstance as TTypeA; 
0
source

Alternatively, you can omit the list class from TCollection and your items from TCollectionItem and use them as base classes. They are already built with all this plumbing. To use your example:

 type TTypeA = class(TCollectionItem); procedure Test; var MyList: TCollection; NewListObject: TTypeA; begin MyList := TCollection.Create(TTypeA); NewListObject := MyList.Add; end; 

Edit: I know that he does not use Generics, but you can look at TCollection and TCollectionItem for more constructive ideas, especially when it comes to property rights, notifications, and life cycle management.

0
source

As far as I know, you can only use a constructor without parameters in the generic class of your general type.

One β€œworkaround” for this problem is to use an anonymous method to create the object, but that means you will need to create many methods.

As for the other problem ...

 TMyObjectList<T:class, constructor> = class(TMyBaseObjectList<T>) TMyBaseObjectList<T:TMyBaseObject> = class(TObjectList) 

I believe that the correct announcement will be

 TMyObjectList<T:TMyBaseObject, constructor> = class(TMyBaseObjectList<T>) TMyBaseObjectList<T:TMyBaseObject> = class(TObjectList) 

TMyBaseObjectList already applies T to the TMyBaseObject type. If you declare T: class in a TMyObjectList, it will not satisfy the requirement of TMyBaseObjectList.

0
source

All Articles