[fpc-devel] Generics Basics
Marc Weustink
marc at dommelstein.net
Wed Nov 9 00:11:55 CET 2005
L505 wrote:
>>The Very Big Advantage (Tm), is that you get syntax checking, while still
>>using a type diversely. That's impossible to do (at compile-time) without
>>generics.
>>
>>Probably the best example of this is something like TList:
>>
>>Without generics:
>>
>>TOrange = class ... end;
>>TApple = class ... end;
>>
>>var
>> T: TList;
>>begin
>> T := TList.Create();
>> T.Add(TApple.Create());
>> T.Add(TOrange.Create());
>> // Whoops, what was that? Now our program might crash.
>>end;
>>
>>Of course, we could create a specialized TAppleList that only accepts Apples,
>>but that's boring and hard work. A much cleaner way is generics:
>>
>>var
>> T: TList<TApple>;
>>begin
>> T := TList<TApple>.Create();
>> T.Add(TApple.Create());
>> T.Add(TOrange.Create());
>> // This wont compile! The problem is prevented at compile-time!
>>end;
>>
>>I hope that answers your question as to why it's a good idea :-)
>>
>>--
>>Regards,
>>Christian Iversen
>
>
>
> Sort of, but I don't see why people use TApple and TOrange examples all the time ;-) I mean
> when was the last time you actually programmed a software application that was organizing
> Apples and Oranges? I use things like strings, databases, integers, FTP, CGI, stringlists,
> etc. Sure apples and oranges can represent a sort of metaphor for ANYTHING, but I'd prefer
> just to cut straight to the real world example instead.
I assume that when ever you wrote some piece of software you needed a
list of something, say a list of integers and a list of objects.
(at least I need them a lot)
you can solve this in various ways.
1) -------------------
you can use an instance of TList and use a lot of casting. I guess you
understand this is pretty unsafe. It requires a lot of dicipline from
you as programmer (and from your co coders)
example 1a (objects in a list):
list := TList.Create;
obj := TMyObject.Create;
list.add(obj);
obj := TMyObject.Create;
list.add(obj);
if you need an object form yuor list, you need
obj := TObject(List[1]); //unsafe cast.
example 1b (integers in a list):
list := TList.Create;
list.add(Pointer(someint)); //typecast needed to add
list.add(Pointer(anotherint));
if you need an integer form yuor list, you need
yourint := Integer(List[1]); //unsafe cast.
2) -------------------
To make things safer, you can create dedicated classes for them with
TList as base class. Since you need specific tipes, you need to override
all methods where TList uses a pointer.
This means write a wrapper for Add, Insert, IndexOf, Get, Set, etc. This
means a lot of coding
TMyIntList.Add(value: Integer)
begin
inherited Add (Pointer(Value));
end;
etc.
3) -------------------
Use generics.
Now you code your TList<T> once like (I assume some syntax here)
type
TList<_T> is class(TObject)
procedure Add(item: _T);
....
end;
Now, when you need a list of intgers, you can declare it as
type
TMyIntList = TList<integer>;
...
list := TMyIntList.Create;
list.Add(someInt);
or even when you need a list of TSomeObject:
type
TMySomeObjectList = TList<TSomeObject>;
...
list := TMySomeObjectList.Create;
obj := TSomeObject.Create;
list.Add(obj);
-------
You understand now ? I only defined/coded one generic list class, and I
can use it to store all kinds of types in a typesafe manner.
The advantage is that I can reuse the (in this case) list code, so I
only have to solve problems in one place, it reduces time, since I don't
have to copy/paste/find/replace existing classes etc.
> I guess the real world examples are hard to display unless you have actually used generics
> in a software program, and you are willing to offer code snippets from the program.
I cannot give you a real world generic example, since it doesn't exist
yet for delphi. And thats where I write programs with. And yes, I've
coded several similar list with all different types.
Marc
More information about the fpc-devel
mailing list