I know the title is Very wide - spanning over a lot !
And I hope that this question might evolve to a bigger "info wiki thingy" on the subjects.
What I have learned - so far:
(please correct me - if you think i'm wrong, missing or have misunderstood anything).
My problem was:
But by now I've spend countless hours, trying to figure out, how to solve this "big puzzle" I have on my desk. And I've gotten some good answers from several of you SO users already - but now its time to get something working in a bigger scale.
I ventured into Generics with this one: Generics and Polymorphism working together
And now I'm kinda stuck on this one: Situations where Generics won't work
Why I end up with covariance problems - is because of my class procedure in my hierarchy.
So I'm wondering if Interfaces is my next bold move in this "saga". How do one "step over" a covariance problem. One thing is to find out that you actually have this problem - another thing is "how to work around it".
So IF any of you good people "out there" has any opinions on this - I'm all ears. Basically : Tell me to go for Interfaces (I have never done one from scratch myself). Or .. throw me a bone in the direction you would suggest.
My current source pool is as stated in the second link - from the top.
Here is a small snippet from my earlier post that shows my covariance problem. David kindly explained - Why I ran into the bush.. But now I need info on - How to run around it.
var
aList : TBaseList<TBaseObject>; // used as a list parameter for methods
aPersonList : TPersonList<TPerson>;
aCustomerList : TCustomerList<TCustomer>;
begin
aPersonList := TPersonList<TPerson>.Create;
aCustomerList := TCustomerList<TCustomer>.Create;
aList := aCustomerList; <-- this FAILS !! types not equal ..
end;
Regards
You can't do what you want to do, but that is not how you use generics anyway. As Rob Kennedy said, it makes no sense to have a TCustomerList<TCustomer>
and a TPersonList<TPerson>
. The beauty of generics is that you can use the same list for different element types. That means that list and element type must not have any dependencies.
You can do something like:
procedure TSomething.ProcessList<T: TBaseObject>(const aList: TBaseList<T>);
begin
// process the list using code that is independent of the actual type of T.
end;
...
var
aCustomerList: TBaseList<TCustomer>;
aPersonList: TBaseList<TPerson>;
begin
ProcessList(aCustomerList);
ProcessList(aPersonList);
Perhaps you may have to specify T
(some early versions of generics did not handle type inference -- i.e. that it inferes the type of T
from the type of the parameter -- very well), i.e.
ProcessList<TCustomer>(aCustomerList);
ProcessList<TPerson>(aPersonList);
But that, or something similar, is what you should do. Anything else doesn't make sense, IMO. There is no need to have a variable that could hold any of these lists, like your aList
. And if you really need one, you can only use TObject
, but that doesn't allow you to use the list in any useful way. And it is not very generic.
Interfaces won't help you at all with this problem. You can give classes certain capabilities, i.e. also the elements of the lists, through interfaces (another kind of polymorphism). But that won't handle covariance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With