Recent

Author Topic: Event handler set to function in object in constructor? possible?  (Read 13993 times)

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Event handler set to function in object in constructor? possible?
« Reply #15 on: October 15, 2017, 04:17:15 pm »
Another newbie question. How do I change GetAppName to return a static string?

Code: [Select]
function GetAppName(): string;
begin
  result := 'Alf';
//  result := AppData.AppName;
end;


mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Re: Event handler set to function in object in constructor? possible?
« Reply #16 on: October 15, 2017, 04:23:13 pm »
I understand. You simply could have taken the example code in the lpr-file and put it in the Create event of your project (if it's GUI). I asked you about it in the thread concerned. If you continued the discussion there, it would have kept things in perspective. ;)

Sorry, I missed your reply of today in the other thread. I'll reply to that one in a few minutes.

The thread was 2 years old and I got a warning regarding this. Also, since I started to "create" my own mistakes and an alternative approach to what the class must be capable of I thought it was best to create a new post.

If you want I can commit the class I'm trying to create (if it gets robust) to your thread in "third-party" as an alternative solution?

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Event handler set to function in object in constructor? possible?
« Reply #17 on: October 15, 2017, 04:25:17 pm »
@mijen67
i've got a solution for your 'problem' but i am not sure if that is the correct approach as i am not too familiar with new class features.

Change your appdata class:
Code: [Select]
  TAppData = class(TObject)
      const AppName: string = '';
      const VendorName: string = '';
    public
      UseLocal: boolean;
    // etc
That seems to work for me.

mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Re: Event handler set to function in object in constructor? possible?
« Reply #18 on: October 15, 2017, 04:25:34 pm »
Another newbie question. How do I change GetAppName to return a static string?

Code: [Select]
function GetAppName(): string;
begin
  result := 'Alf';
//  result := AppData.AppName;
end;


Got it! (That is pretty static ...  :D )

mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Re: Event handler set to function in object in constructor? possible?
« Reply #19 on: October 15, 2017, 04:31:29 pm »
@mijen67
i've got a solution for your 'problem' but i am not sure if that is the correct approach as i am not too familiar with new class features.

Change your appdata class:
Code: [Select]
  TAppData = class(TObject)
      const AppName: string = '';
      const VendorName: string = '';
    public
      UseLocal: boolean;
    // etc
That seems to work for me.

Great! Works here as well.
Now, it would be nice to find out why  :)

munair

  • Hero Member
  • *****
  • Posts: 798
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: Event handler set to function in object in constructor? possible?
« Reply #20 on: October 15, 2017, 04:33:19 pm »
If you want I can commit the class I'm trying to create (if it gets robust) to your thread in "third-party" as an alternative solution?
Feel free to add your code to the Third Party section as a new contribution.
keep it simple

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Event handler set to function in object in constructor? possible?
« Reply #21 on: October 15, 2017, 04:38:13 pm »
Now, it would be nice to find out why  :)
atm i have no idea. It has to do with class initialization and order in which things are 'done' internally.

better approach for your situation might be:
Code: [Select]
  TAppData = class(TObject)
    public
      class var AppName: String;
      class var VendorName: String;
      UseLocal: boolean;
     // etc.

The const solution was the first thing i could think of, but your filednames are actually more like variables.

edit: ah, fields defined this way are just plain static fields. so you can also use:
Code: [Select]
  TAppData = class(TObject)
    public
      AppName: String; static;
      VendorName: String; static;
      UseLocal: boolean;
    // etc.
More on static variables can be read here.

afaik that also implies that when you initialize your class inside the constructor that (indirectly) your GetAppName and GetVendorName routines are invoked when your statements inside method TAppData.GetDirectories are executed. Since your class is not initialized completely yet (construction hasn't finished yet) the fields are not accessible. Turning them into static fields allows you to access them even when you did not created your class (so these fields behave differently).
« Last Edit: October 15, 2017, 04:58:19 pm by molly »

mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Re: Event handler set to function in object in constructor? possible?
« Reply #22 on: October 15, 2017, 04:55:01 pm »
If you want I can commit the class I'm trying to create (if it gets robust) to your thread in "third-party" as an alternative solution?
Feel free to add your code to the Third Party section as a new contribution.

Thanks!
Off course with a section with credits to all that helped get this to work.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Event handler set to function in object in constructor? possible?
« Reply #23 on: October 15, 2017, 04:58:49 pm »
Previous post updated. Might be important for you @mijen67

munair

  • Hero Member
  • *****
  • Posts: 798
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: Event handler set to function in object in constructor? possible?
« Reply #24 on: October 15, 2017, 05:04:07 pm »
The attachment contains the original example project (set to Linux platform). I adjusted a few things and it should compile fine.

The reason I put the code in the lpr file is that it prevents the main form from being instantiated if initial tests fail. There may be a better approach, but this is how I did it two years ago.

BTW, there is nothing wrong with having private procedures / functions in a unit as in this example (rather than including them inside the class). It may keep things simple.
« Last Edit: October 15, 2017, 05:15:08 pm by munair »
keep it simple

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Event handler set to function in object in constructor? possible?
« Reply #25 on: October 15, 2017, 07:17:48 pm »
The reason I put the code in the lpr file is that it prevents the main form from being instantiated if initial tests fail. There may be a better approach, but this is how I did it two years ago.
Not saying better but you could use unit initialization/finalization as suggested by user Eugene.

Both have the advantage that the code is running prior to app initialization.

Another method is by adding a datamodule, and making sure that module is the first 'form' to be (auto) created. Of course in that case App init has already taken place (and might have failed). That also means that the initialization of your custom class might be done too late for its purpose/usage.

You could also extend/override original TApplication class as well.

Quote
BTW, there is nothing wrong with having private procedures / functions in a unit as in this example (rather than including them inside the class). It may keep things simple.
Indeed there is nothing wrong with that and in some occasions might even be preferred.
« Last Edit: October 15, 2017, 07:22:16 pm by molly »

mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Re: Event handler set to function in object in constructor? possible?
« Reply #26 on: October 17, 2017, 10:27:27 am »
You may even automatically create it in initialization section and automatically free it in finalization section. However, that means it will be only one instance (which is actually wise).

Great idea! Thanks!
I used the initialization section to instantiate an object of the class. This solved the issues with access violation I had previously.

Based on this idea, I've created two units: one called uAppData.pas and one called uProgSettings.pas. The former is for "clearing the path" to get a configuration file, and the latter is application specific mainly for handling the ini-file for user settings.

However, now I have "timing" problem.
When I run the program first time it fails with:
Unable to open file <pathremoved>\grp_gen.ini
line 96 of uprogsettings.pas
line 7 of project1.lpr


When I run the program the second time, it (seems) to work as intended.

It seems uAppData initialization section isn't finalized before uProgSettings initialization section starts? (Or it may be a completely different issue).

How can I control this so that AppData has created the .ini file before uProgSetting initialization section is run?
« Last Edit: October 17, 2017, 11:35:34 am by mijen67 »

munair

  • Hero Member
  • *****
  • Posts: 798
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: Event handler set to function in object in constructor? possible?
« Reply #27 on: October 17, 2017, 10:36:18 am »
Great idea! Thanks!
I used the finalization section to instantiate an object of the class. This solved the issues with access violation I had previously.
The finalization section is executed at program end, so instantiating an object there doesn't make sense.

Instantiate your object in the Initialization section or in the Form Create handler. Free your object in the Finalization section or in the Form Close handler...
keep it simple

mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Re: Event handler set to function in object in constructor? possible?
« Reply #28 on: October 17, 2017, 11:34:59 am »
Great idea! Thanks!
I used the finalization section to instantiate an object of the class. This solved the issues with access violation I had previously.
The finalization section is executed at program end, so instantiating an object there doesn't make sense.

Instantiate your object in the Initialization section or in the Form Create handler. Free your object in the Finalization section or in the Form Close handler...

Typo, it was instantiated in the initialization section, I'll correct the text above.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Event handler set to function in object in constructor? possible?
« Reply #29 on: October 17, 2017, 01:46:56 pm »
How can I control this so that AppData has created the .ini file before uProgSetting initialization section is run?
i only had a quick glance (so might be off) but you need to include your units in the correct order. Initialization sections are 'run' in the order: first comes, first serves. (and the reverse order of that on finalization).

So when i read:
Code: [Select]
uses uLibFunctions1, uLogSimple1, uAppData, uProgSettings, IniFiles;
That means following order:
Code: [Select]
uAppData.Initialization
uProgSettings.Initialization
.lpr file
uProgSettings.Finalization
uAppData.Finalization
From that i assume you are able to grasp why things go wrong. Also note that you are allowed to include units at any other location (so order might not be the same as listed in .lpr file alone). Don't forget about interface _and_ implementation sections.
« Last Edit: October 17, 2017, 01:48:53 pm by molly »

 

TinyPortal © 2005-2018