>Global variables means non-object-oriented, non-reusable,
>non-understandable, non-maintainable code. Try building a large project
>with everything global and find out!
Your friend and mine, the Delphi IDE automatically creates a global variable
for each form you design. If they're that bad, why would the IDE create
them? From a simplicity point of view, they can come in very handy. In the
case of global form variables, I usually put something like this in my
Form's OnDestroy event:
procedure TMyForm.FormDestroy( Sender : TObject );
begin
if self = MyForm then
MyForm := nil;
end;
At least that way the global is kept up to date, so code can use if
assigned( MyForm ) etc.
Another way of dealing with the global form variable declaration is to
remove the form variable and create some kind of constructor variable. eg:
type
TMyForm = class( TForm )
// stuff that your TMyForm should be able to do
end;
then instead of
var
MyForm : TMyForm;
delete the IDE created variable and add
type
TCreateMyForm = function( aOwner : TComponent ) : TMyForm;
var
CreateMyForm : TMyForm;
In the implementation section of your unit, create an actual virtual
constructor like
function DefaultCreateMyForm( aOwner : TComponent ) : TMyForm;
begin
result := TMyForm.Create( aOwner );
end;
in the initialization section of the same unit you can put
initialization
@CreateMyForm := @DefaultCreateMyForm;
end.
The @ signs are needed.
The upshot of all of this is that you can now have code that does something
like
if assigned( CreateMyForm ) then
with CreateMyForm( self ) do
try
ShowModal;
finally
free;
end;
Woopee! But the good bit, is that now you have a global virtual form
constructor to work with in your code, it can be overriden without needing
to change anything in the original code that called it.
eg:
interface
uses MyForm;
TMyReallyNeatForm = class( TMyForm )
// something that makes your really neat form really neat
end;
Build a virtual constructor in the same unit (implementation section):
function CreateMyReallyNeatFormForm( aOwner : TComponent ) : TMyForm;
begin
result := TMyReallyNeatFormCreate( aOwner );
end;
and in the initialization section of the RealllyNeatForm unit
initialization
@CreateMyForm := @CreateMyReallyNeatForm;
end.
You can do things like chaining (and you probably should if you are loading
and unloading packages) but the point is that without those global
variables, you couldn't do this at all.
If you can get your head around how this stuff can be made to work for you,
then you probably have the basis for a good argument for using global
variables. If not, then spend some more time thinking about why a variable
should be global or not.
Some globals that I use regularly are Application and Screen. Can you
imagine trying to do much in Delphi if they weren't global? If you think
about why they are made global, and why form variables are made global, the
whole global versus local argument starts to make sense.
It should be global if It NEEDS to be referred to from anywhere. If you
are going to be able to override a function variable then it definitely
NEEDS to be referred to from anywhere.
If the variable doesn't NEED to be available from anywhere then it shouldn't
be global.
There's also another class of globals in Delphi. Hidden globals. They are
globals which are declared only in the implementation section of a unit.
They are global to the unit, but invisible from outside the unit. You might
have a TList which keeps track of instances of classes that you create. eg:
interface
type
TMyclass = class
// cool stuff
public
constructor Create;
destructor Destroy; override;
end;
implementation
var
MyClassList : TList;
constructor TMyClass.create;
begin
inherited Create;
if not assigned( MyClassList ) then
MyClassList := TList.Create;
MyClassList.Add( self )
end;
destructor TMyClass.Destroy;
begin
if MyClassList.IndexOf(self ) >= 0 then
MyClassList.Delete( MyClassList.IndexOf( self ));
if MyClassList.Coujnt = 0 then
FreeAndNil( MyClassList );
inherited Destroy;
end;
In this case the MyClassList is available to any part of the implementation
of the TMyClass.
Useful if you are using Window Regions or Window Hooks or a whole bunch of
things that I haven't thought of.
In this case the MyClassList NEEDS to be made available to anything in the
implementation that uses it, therefore it should be global to the
implementation. Otherwise forget global. And if you need hidden global
like I've just described, then make sure it stays hidden.
My 2 cents, I hope that it helps someone
---------------------------------------------------------------------------
New Zealand Delphi Users group - Delphi List - [EMAIL PROTECTED]
Website: http://www.delphi.org.nz
To UnSub, send email to: [EMAIL PROTECTED]
with body of "unsubscribe delphi"