Class/Static Constants in Delphi

前端 未结 9 717
粉色の甜心
粉色の甜心 2021-02-05 12:06

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:

pub         


        
相关标签:
9条回答
  • 2021-02-05 12:44

    Two questions I think that need to be answered before you come up with a "perfect" solution..

    • The first, is whether TLogLogger is thread-safe. Can the same TLogLogger be called from multiple threads without calls to "syncronize"? Even if so, the following may still apply
    • Are class variables thread-in-scope or truly global?
    • 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

    Code:

    interface
    type
      TMyObject = class(TObject)
      private
        FLogger: TLogLogger; //NB: pointer to shared threadvar
      public
        constructor Create;
      end;
    implementation
    threadvar threadGlobalLogger: TLogLogger = nil;
    constructor TMyObject.Create;
    begin
      if not Assigned(threadGlobalLogger) then
        threadGlobalLogger := TLogLogger.GetLogger(TMyObject); //NB: No need to reference count or explicitly free, as it's freed by Log4D
      FLogger := threadGlobalLogger;
    end;
    

    Edit: It seems that class variables are globally stored, rather than an instance per thread. See this question for details.

    0 讨论(0)
  • 2021-02-05 12:45

    Here is how I'll do that using a class variable, a class procedure and an initialization block:

    unit MyObject;
    
    interface
    
    type
    
    TMyObject = class
       private
         class var FLogger : TLogLogger;
       public
         class procedure SetLogger(value:TLogLogger);
         class procedure FreeLogger;
       end;
    
    implementation
    
    class procedure TMyObject.SetLogger(value:TLogLogger);
    begin
      // sanity checks here
      FLogger := Value;
    end;
    
    class procedure TMyObject.FreeLogger;
    begin
      if assigned(FLogger) then 
        FLogger.Free;
    end;
    
    initialization
      TMyObject.SetLogger(TLogLogger.Create);
    finalization
      TMyObject.FreeLogger;
    end.
    
    0 讨论(0)
  • 2021-02-05 12:54

    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:

    unit MyObject;
    
    interface
    
    type
    
    TMyObject = class
    private
      class var FLogger: TLogLogger;
    end;
    
    implementation
    
    initialization
      TMyObject.FLogger:= TLogLogger.GetLogger(TMyObject);
    finalization
      // You'd typically want to free the class objects in the finalization block, but
      // TLogLoggers are actually managed by Log4D.
    
    end.
    

    Perhaps a little more object oriented would be something like:

    unit MyObject;
    
    interface
    
    type
    
    TMyObject = class
    strict private
      class var FLogger: TLogLogger;
    private
      class procedure InitClass;
      class procedure FreeClass;
    end;
    
    implementation
    
    class procedure TMyObject.InitClass;
    begin
      FLogger:= TLogLogger.GetLogger(TMyObject);
    end;
    
    class procedure TMyObject.FreeClass;
    begin
      // Nothing to do here for a TLogLogger - it's freed by Log4D.
    end;
    
    initialization
      TMyObject.InitClass;
    finalization
      TMyObject.FreeClass;
    
    end.
    

    That might make more sense if there were multiple such class constants.

    0 讨论(0)
提交回复
热议问题