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


_______________________________________________
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply via email to