tags:

views:

561

answers:

6

Is it in Delphi (Win32) possible to declare a whole class (not only a function of the class) as static?

+3  A: 

I assume you mean static classes like in .net (and not "static" as in traditional Delphi/Native) - and the answer to that is no.

Lars D
Maybe this can help you understand why: Static classes are often used for encapsulation in ways that are similar to units in Delphi.
Lars D
I'd prefer not to assume. Can you please make it blatantly obvious what *you* mean by *static*?
Rob Kennedy
+2  A: 

I am not quite sure what you mean by a "static class". You can declare a class, that has only class methods, so these methods can be called without instantiating the class.

TSomeClass.SomeMethod;

Is that what you want?

dummzeuch
+2  A: 

Not natively.

Depending on what you need it for, if for the purposes of your code, in some use cases you could replace it with a Singleton Pattern object.

For walkthrough on implementing this I'd recommend this guide which, covers almost any version of delphi, but if you're using Delphi 2010 you could also use the new class Constructors/Destructors for improved results.

jamiei
A: 

You can also create a new unit called uDG_Utils for example, define a class, define a global variable for that class and in the initialization and finalization section you manage the class constructor and destructor. Now all you need to do is call it like mySuperDuperClass.SuperMethod...

delphigeist
A: 

You could create a class that contains nothing but static methods. If you have to maintain some sort of state, then the state variables should be passed as var parameters. There is no way to "properly" access static variables other than having a set of global variables in the implementation section of the class OUTSIDE the scope of the class, for example:

UNIT TestUnit;

INTERFACE

Type
  TStaticClass = Class
  public
    procedure Foo(var Bar:String); static;
  end;

IMPLEMENTATION

var
  LastBar : String; // the last bar
  LastRes : string; // the last result

Procedure TStaticClass.Foo(var Bar:String);
begin
  if Bar <> LastBar then
    LastRes := SomeCPUExpensiveProcess(Bar);
  LastBar := Bar;
  Bar := LastRes;
end;

INITIALIZATION
  LastBar := '';
  LastRes := SomeCPUExpensiveProcess('');
END.
skamradt
A: 

(Yes, I know this thread is old, but thought I'd post this for posterity.)

It's been pointed out that class functions and class procedures implement static methods. But I'll add that the next notable behavior of a static class (vs a Delphi class) is that a static class cannot be instantiated.

Delphi classes get a public default (parameterless) constructor if you do not specify one, so any class can be instantiated. If you declare one or more constructors explicitly, this constructor is not provided.

You can remove all constructors by declaring a constructor in the private or protected section of your class. This removes your constructor from the scope of the consumer. Now there is only one constructor, it is not visible and the class cannot be instantiated.

Example:

type
  TMyStaticClass = class(TObject)
  private
    // Hide the default constructor, suppressing hint H2219.
    {$HINTS OFF} constructor Create; {$HINTS ON}
  public
    class procedure Method1; // A static method
  end;

implementation

constructor TMyStaticClass.Create;
begin
  // Do nothing.  This cannot be called.
end;

class procedure TMyStaticClass.Method1();
begin
  // Do something here.
end;

If you have one of the newer versions of Delphi, you may also consider sealing the class just to be a bit more proper. Descendant classes COULD be instantiated if your constructor is protected rather than private.


Edit

Here is an alternative, inspired by Ken, for newer Delphi versions (which support sealed classes) which does not incur a compiler hint. It's still not a perfect solution, but here it is.

unit Unit1;

interface

type
  TMyStaticClass = class sealed (TObject)
  protected
    constructor Create;
  public
    class procedure Method1; // A static method
  end;

implementation

constructor TMyStaticClass.Create;
begin
  // Do nothing.  This cannot be called.
end;

class procedure TMyStaticClass.Method1();
begin
  // Do something here.
end;

end. 
Phil Gilmore
The fact that you're having to turn hints off should tell you that this is poor code.
Ken White
He's asking for a feature that's not supported, so no solution is going to be perfect.As for hints, I would normally agree and don't condone turning off hints. The hints are usually right and point out mistakes that can be serious and elusive. But look closer at this case. 1- The code produces NO hint in Delphi 7. So is it poor code in Delphi 2010 but not in Delphi 7? Well, maybe.2- The warning is "declared but never used". If you change the private to protected and seal the class in 2010, .Create is still hidden but the hint goes away. Does that make it better? ...
Phil Gilmore
... I tend to think not. But let me be clear; I don't think you're wrong, just that this particular case is a possible exception and that I think it's the lesser of many evils, such as throwing an exception in a public constructor to prevent instantiation.In any case, even this one, your point is valid and I don't want to discourage anyone from considering it.
Phil Gilmore
@Phil: A novel idea. However, I don't think you've ever tested this... **It doesn't work**. The default `constructor TObject.Create();` cannot be "removed"! If you implement a constructor with a different name, `Create()` can still be called. If you implement a constructor with the same name but lower visibility, then the default will be called if yours is out of scope.
Craig Young