[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
>>Probably the best example of this is something like TList:
>>Without generics:
>>TOrange = class ... end;
>>TApple  = class ... end;
>>  T: TList;
>>  T := TList.Create();
>>  T.Add(TApple.Create());
>>  T.Add(TOrange.Create());
>>  // Whoops, what was that? Now our program might crash.
>>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:
>>  T: TList<TApple>;
>>  T := TList<TApple>.Create();
>>  T.Add(TApple.Create());
>>  T.Add(TOrange.Create());
>>  // This wont compile! The problem is prevented at compile-time!
>>I hope that answers your question as to why it's a good idea :-)
>>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;
obj := TMyObject.Create;

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

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)
   inherited Add (Pointer(Value));


3) -------------------

Use generics.
Now you code your TList<T> once like (I assume some syntax here)

   TList<_T> is class(TObject)
     procedure Add(item: _T);

Now, when you need a list of intgers, you can declare it as

   TMyIntList = TList<integer>;

list := TMyIntList.Create;

or even when you need a list of TSomeObject:

   TMySomeObjectList = TList<TSomeObject>;

list := TMySomeObjectList.Create;
obj := TSomeObject.Create;

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.


More information about the fpc-devel mailing list