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