Declare public global variable in Delphi

后端 未结 3 931
余生分开走
余生分开走 2021-01-01 21:47

Let\'s say I have two forms in a delphi project, I want to be able to access form1\'s variables from form2. Is there anyone to declare, say a \'public\' variable in form1 wh

相关标签:
3条回答
  • 2021-01-01 22:06

    the example shows Form1(main) and Form2(other) which has better use for organization;


    FORM1 interface declaration only;

    can be read from all forms;

    interface
    
    procedure oncreate(Sender: TObject);
    
    implementation
    uses Form2;
    
    procedure TForm1.oncreate(Sender: TObject);
    begin
      Form2.test1;
      //{Form2.test2} are not visible to Form1;
    end;
    

    FORM2 interface and implementation declarations;

    implementation declaration are local to the unit; cannot be read from all forms;

    interface
    
    procedure test1;
    
    implementation
    
    procedure test2; //declared under implementation;
    
    procedure TForm2.test1;
    begin
      ShowMessage('form2 test1 message');
    end;
    
    procedure TForm2.test2;
    begin
      ShowMessage('form2 test2 message');
    end;
    


    any procedure, function, type, variable can be local to the unit under implementation;
    it also makes intellisense(Ctrl+Space) clean from declarations used only to the unit;

    0 讨论(0)
  • 2021-01-01 22:09

    First, if you must use globals (it's probably better not to use globals, as Craig has wisely pointed out) then you should put the globals you want to share in SharedGlobals.pas:

    unit SharedGlobals;
    interface
    var
       {variables here}
       Something:Integer;
    implementation
        { nothing here?}
    

    Now use that unit, from the two units you want to share access to that variable in. Alternatively, have both reference another object, which is named something sensible, and have that object be designed, as the holder of state (variable values) that those two instances (forms or classes, or whatever) need to share.

    Second idea, since your two units that you have already have dependencies on each other, you could also get around your circular dependency by using the unit that would create a circular dependency, from the implementation section instead of the interface:

     unit Unit2;
     interface
       /// stuff
     implementation
        uses Unit1; 
    

    ...

     unit Unit1;
     interface
       /// stuff
     implementation
        uses Unit2; 
    
    0 讨论(0)
  • 2021-01-01 22:21

    First, it's better to pretend that globals don't exist at all. If you start out programming with the crutch of global variables, you'll just avoid learning the very simple techniques that allow you to do without them. You're worrying about using pointers (which actually wouldn't help your problem at all), but not concerned about using globals which are actually more dangerous.

    Globals are dangerous because:

    • They provide a link between the units that share them (a concept called tight coupling)
    • This link is hidden in the sense that it's not obvious the exact nature of the link without examining the detail of the code.
    • Your code will become littered with side effects, which is to say that when you do something in a method, other unexpected things happen as well. This increases the possibility and complexity of subtle bugs.
    • The cumulative effect of the above points is that even if you break a project down into 20 units, your brain still has to think about all 20 units at the same time - as if they were only1 unit. This defeats the purpose of breaking your project down into smaller manageable units in the first place.
    • You'll quickly find that even medium sized projects start becoming very difficult to maintain.

    Circular References

    Please take a look at my answer to a previous question for thoughts on dealing with circular references more generally.

    In your case, you simply need to move Unit1 from the interface uses to the implementation uses.

    var
      Form2: TForm2; 
    
    implementation
    
    uses
      Unit1;
    
    {$R *.lfm}
    
    { TForm2 }
    
    procedure TForm2.FormCreate(Sender: TObject);
    begin
      Form1.test; //Is now accessible, but remember: it will cause a runtime error if Form1 hasn't been created or has already been destroyed.
    end;
    

    Sharing data without globals

    You'll notice that technically you're still using globals; albeit ones created by Delphi and not your own. Here's a technique you can use to share data in a more controlled fashion.

    unit Unit3;
    
    interface
    
    type
      TSharedData = class(TObject)
      public
        Test1: Integer;
        Test2: Integer;
      end;
    

    Then in Form1 you add the following:

    implementation
    
    uses
      ...
      Unit3;
    
    type
      TForm1 = class(TForm)
      ...
      public
        SharedData: TSharedData;
      end;
    
    //Inside either the constructor or OnCreate event add the following line:
    SharedData := TSharedData.Create;
    //Inside either the destructor or OnDestroyevent add the following line:
    SharedData.Free;
    

    Then in Form2 you do something slightly different because you want to use Form1's shared data not its own "shared data".

    implementation
    
    uses
      ...
      Unit3;
    
    type
      TForm2 = class(TForm)
      ...
      public
        Form1SharedData: TSharedData;
      end;
    
    //Nothing added to constructor/destructor or OnCreate/OnDestroy events
    

    Finally, after creating both forms, you give Form2 a refernce to Form1's shared data:

    procedure RunApplicationWithoutFormGlobals;
    var
      LForm1: TForm1;
      LForm2: TForm2;
    begin
      Application.Initialize;
      Application.MainFormOnTaskbar := True;
      Application.CreateForm(TForm1, LForm1);
      Application.CreateForm(TForm2, LForm2);
      LForm2.Form1SharedData := LForm1.SharedData;
      Application.Run;
    end;
    

    The above illustrates how easily you can do away with even Delphi's global variables.


    Disclaimer: Some of the code goes agaisnt generally accepted encapsulation principles, but is for illustrative purposes only.

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