<p>In Delphi, I want to be able to create an private object that's associated with a class, and access it from all instances of that class.  In Java, I'd use:</p>

<pre><code>public class MyObject {
    private static final MySharedObject mySharedObjectInstance = new MySharedObject();
}
</code></pre>

<p>Or, if MySharedObject needed more complicated initialization, in Java I could instantiate and initialize it in a static initializer block.</p>

<p>(You might have guessed...  I know my Java but I'm rather new to Delphi...)</p>

<p>Anyway, I don't want to instantiate a new MySharedObject each time I create an instance of MyObject, but I do want a MySharedObject to be accessible from each instance of MyObject.  (It's actually logging that has spurred me to try to figure this out - I'm using Log4D and I want to store a TLogLogger as a class variable for each class that has logging functionality.)</p>

<p>What's the neatest way to do something like this in Delphi?</p>

[{'answer_id': 71811, 'author': 'CL.', 'author_id': 11654, 'author_profile': 'https://Stackoverflow.com/users/11654', 'pm_score': 0, 'selected': False, 'text': "<p>Before version 7, Delphi didn't have static variables, you'd have to use a global variable.</p>\n\n<p>To make it as private as possible, put it in the <code>implementation</code> section of your unit.</p>\n"}, {'answer_id': 71841, 'author': 'squadette', 'author_id': 7754, 'author_profile': 'https://Stackoverflow.com/users/7754', 'pm_score': 0, 'selected': False, 'text': '<p>In Delphi static variables are implemented as <em>variable types constants</em> :)</p>\n\n<p>This could be somewhat misleading.</p>\n\n<pre><code>procedure TForm1.Button1Click(Sender: TObject) ;\nconst\n   clicks : Integer = 1; //not a true constant\nbegin\n  Form1.Caption := IntToStr(clicks) ;\n  clicks := clicks + 1;\nend;\n</code></pre>\n\n<p>And yes, another possibility is using global variable in <code>implementation</code> part of your module.</p>\n\n<p>This only works if the compiler switch "Assignable Consts" is turned on, globally or with <code>{$J+}</code> syntax (tnx Lars).</p>\n'}, {'answer_id': 71889, 'author': 'Lars Fosdal', 'author_id': 10002, 'author_profile': 'https://Stackoverflow.com/users/10002', 'pm_score': 2, 'selected': False, 'text': '<pre><code> TMyObject = class\n    private\n      class var FLogger : TLogLogger;\n      procedure SetLogger(value:TLogLogger);\n      property Logger : TLogLogger read FLogger write SetLogger;\n    end;\n\nprocedure TMyObject.SetLogger(value:TLogLogger);\nbegin\n  // sanity checks here\n  FLogger := Value;\nend;\n</code></pre>\n\n<p>Note that this class variable will be writable from any class instance, hence you can set it up somewhere else in the code, usually based on some condition (type of logger etc.).</p>\n\n<p>Edit: It will also be the same in all descendants of the class.  Change it in one of the children, and it changes for all descendant instances.\nYou could also set up default instance handling.</p>\n\n<pre><code> TMyObject = class\n    private\n      class var FLogger : TLogLogger;\n      procedure SetLogger(value:TLogLogger);\n      function GetLogger:TLogLogger;\n      property Logger : TLogLogger read GetLogger write SetLogger;\n    end;\n\nfunction TMyObject.GetLogger:TLogLogger;\nbegin\n  if not Assigned(FLogger)\n   then FLogger := TSomeLogLoggerClass.Create;\n  Result := FLogger;\nend;\n\nprocedure TMyObject.SetLogger(value:TLogLogger);\nbegin\n  // sanity checks here\n  FLogger := Value;\nend;\n</code></pre>\n'}, {'answer_id': 71993, 'author': 'Graza', 'author_id': 11820, 'author_profile': 'https://Stackoverflow.com/users/11820', 'pm_score': 2, 'selected': False, 'text': '<p>The keywords you are looking for are "class var" - this starts a block of class variables in your class declaration. You need to end the block with "var" if you wish to include other fields after it (otherwise the block may be ended by a "private", "public", "procedure" etc specifier). Eg </p>\n\n<p>(Edit: I re-read the question and moved reference count into TMyClass - as you may not be able to edit the TMySharedObjectClass class you want to share, if it comes from someone else\'s library)</p>\n\n<pre><code>  TMyClass = class(TObject)\n  strict private\n    class var\n      FMySharedObjectRefCount: integer;\n      FMySharedObject: TMySharedObjectClass;\n    var\n    FOtherNonClassField1: integer;\n    function GetMySharedObject: TMySharedObjectClass;\n  public\n    constructor Create;\n    destructor Destroy; override;\n    property MySharedObject: TMySharedObjectClass read GetMySharedObject;\n  end;\n\n\n{ TMyClass }\nconstructor TMyClass.Create;\nbegin\n  if not Assigned(FMySharedObject) then\n    FMySharedObject := TMySharedObjectClass.Create;\n  Inc(FMySharedObjectRefCount);\nend;\n\ndestructor TMyClass.Destroy;\nbegin\n  Dec(FMySharedObjectRefCount);\n  if (FMySharedObjectRefCount &lt; 1) then\n    FreeAndNil(FMySharedObject);\n\n  inherited;\nend;\n\nfunction TMyClass.GetMySharedObject: TMySharedObjectClass;\nbegin\n  Result := FMySharedObject;\nend;\n</code></pre>\n\n<p>Please note the above is not thread-safe, and there may be better ways of reference-counting (such as using Interfaces), but this is a simple example which should get you started. Note the TMySharedObjectClass can be replaced by TLogLogger or whatever you like.</p>\n'}, {'answer_id': 72047, 'author': 'Pierre-Jean Coudert', 'author_id': 8450, 'author_profile': 'https://Stackoverflow.com/users/8450', 'pm_score': 5, 'selected': True, 'text': "<p>Here is how I'll do that using a class variable, a class procedure and an initialization block:</p>\n\n<pre><code>unit MyObject;\n\ninterface\n\ntype\n\nTMyObject = class\n   private\n     class var FLogger : TLogLogger;\n   public\n     class procedure SetLogger(value:TLogLogger);\n     class procedure FreeLogger;\n   end;\n\nimplementation\n\nclass procedure TMyObject.SetLogger(value:TLogLogger);\nbegin\n  // sanity checks here\n  FLogger := Value;\nend;\n\nclass procedure TMyObject.FreeLogger;\nbegin\n  if assigned(FLogger) then \n    FLogger.Free;\nend;\n\ninitialization\n  TMyObject.SetLogger(TLogLogger.Create);\nfinalization\n  TMyObject.FreeLogger;\nend.\n</code></pre>\n"}, {'answer_id': 72496, 'author': 'PatrickvL', 'author_id': 12170, 'author_profile': 'https://Stackoverflow.com/users/12170', 'pm_score': 3, 'selected': False, 'text': '<p>Last year, Hallvard Vassbotn blogged about a Delphi-hack I had made for this, it became a two-part article:</p>\n\n<ol>\n<li><a href="http://hallvards.blogspot.com/2007/05/hack17-virtual-class-variables-part-i.html" rel="noreferrer">Hack#17: Virtual class variables, Part I</a></li>\n<li><a href="http://hallvards.blogspot.com/2007/05/hack17-virtual-class-variables-part-ii.html" rel="noreferrer">Hack#17: Virtual class variables, Part II</a></li>\n</ol>\n\n<p>Yeah, it\'s a long read, but very rewarding.</p>\n\n<p>In summary, I\'ve reused the (deprecated) VMT entry called vmtAutoTable as a variable.\nThis slot in the VMT can be used to store any 4-byte value, but if you want to store, you could always allocate a record with all the fields you could wish for.</p>\n'}, {'answer_id': 73486, 'author': 'MB.', 'author_id': 11961, 'author_profile': 'https://Stackoverflow.com/users/11961', 'pm_score': 1, 'selected': False, 'text': "<p>For what I want to do (a private class constant), the neatest solution that I can come up with (based on responses so far) is:</p>\n\n<pre><code>unit MyObject;\n\ninterface\n\ntype\n\nTMyObject = class\nprivate\n  class var FLogger: TLogLogger;\nend;\n\nimplementation\n\ninitialization\n  TMyObject.FLogger:= TLogLogger.GetLogger(TMyObject);\nfinalization\n  // You'd typically want to free the class objects in the finalization block, but\n  // TLogLoggers are actually managed by Log4D.\n\nend.\n</code></pre>\n\n<p>Perhaps a little more object oriented would be something like:</p>\n\n<pre><code>unit MyObject;\n\ninterface\n\ntype\n\nTMyObject = class\nstrict private\n  class var FLogger: TLogLogger;\nprivate\n  class procedure InitClass;\n  class procedure FreeClass;\nend;\n\nimplementation\n\nclass procedure TMyObject.InitClass;\nbegin\n  FLogger:= TLogLogger.GetLogger(TMyObject);\nend;\n\nclass procedure TMyObject.FreeClass;\nbegin\n  // Nothing to do here for a TLogLogger - it's freed by Log4D.\nend;\n\ninitialization\n  TMyObject.InitClass;\nfinalization\n  TMyObject.FreeClass;\n\nend.\n</code></pre>\n\n<p>That might make more sense if there were multiple such class constants.</p>\n"}, {'answer_id': 81437, 'author': 'Graza', 'author_id': 11820, 'author_profile': 'https://Stackoverflow.com/users/11820', 'pm_score': 1, 'selected': False, 'text': '<p>Two questions I think that need to be answered before you come up with a "perfect" solution..</p>\n\n<ul>\n<li>The first, is whether TLogLogger is thread-safe. Can the same TLogLogger be called from multiple threads <em>without</em> calls to "syncronize"? Even if so, the following may still apply</li>\n<li>Are class variables thread-in-scope or truly global?</li>\n<li>If class variables are truly global, and TLogLogger is not thread safe, you might be best to use a unit-global threadvar to store the TLogLogger (as much as I don\'t like using "global" vars in any form), eg</li>\n</ul>\n\n<p>Code:</p>\n\n<pre><code>interface\ntype\n  TMyObject = class(TObject)\n  private\n    FLogger: TLogLogger; //NB: pointer to shared threadvar\n  public\n    constructor Create;\n  end;\nimplementation\nthreadvar threadGlobalLogger: TLogLogger = nil;\nconstructor TMyObject.Create;\nbegin\n  if not Assigned(threadGlobalLogger) then\n    threadGlobalLogger := TLogLogger.GetLogger(TMyObject); //NB: No need to reference count or explicitly free, as it\'s freed by Log4D\n  FLogger := threadGlobalLogger;\nend;\n</code></pre>\n\n<p><em>Edit: It seems that class variables are globally stored, rather than an instance per thread. See <a href="https://stackoverflow.com/questions/82113/are-delphi-class-vars-global-or-thread-in-storage">this question</a> for details.</em></p>\n'}, {'answer_id': 1038253, 'author': 'Gedean Dias', 'author_id': 101900, 'author_profile': 'https://Stackoverflow.com/users/101900', 'pm_score': 2, 'selected': False, 'text': "<p>Well, it's not beauty, but works fine in Delphi 7:</p>\n\n<pre><code>TMyObject = class\npulic\n    class function MySharedObject: TMySharedObject; // I'm lazy so it will be read only\nend;\n\nimplementation\n</code></pre>\n\n<p>...</p>\n\n<pre><code>class function MySharedObject: TMySharedObject;\n{$J+} const MySharedObjectInstance: TMySharedObject = nil; {$J-} // {$J+} Makes the consts writable\nbegin\n    // any conditional initialization ...\n   if (not Assigned(MySharedObjectInstance)) then\n       MySharedObjectInstance = TMySharedOject.Create(...);\n  Result := MySharedObjectInstance;\nend;\n</code></pre>\n\n<p>I'm curently using it to build singletons objects.</p>\n"}]
['https://Stackoverflow.com/questions/71766', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/11961/']