Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Inheritance Question 1

Status
Not open for further replies.

Delphard

Programmer
Jul 22, 2004
144
RS
Form1 is ancestor Form, and had this code in Form1.FormClose:
...
Action:= caFree;
Form1 := nil;
end;

Form2 is derived from Form1 (TForm2 = class(TForm1).

What should write instead of Form1 := nil in Form1.FormClose to be sure that (inherited) Form2 is also nil after Close?
 
<formname>.Free seems like the obvious answer to me, but why not nil? That should work just fine?

[bobafett] BobbaFet [bobafett]
Code:
if not Programming = 'Severe Migraine' then
                       ShowMessage('Eureka!');
 
Exactly that is and my question:
what is <formname>?
 
Let me get this straight in my head:

You've got form SomeForm, you derived another form from it. Now you want to make sure that when SomeForm is closed, the derived form is closed as well, right?

How do you create the derived form? Are we talking about a component that happens to be a form?

[bobafett] BobbaFet [bobafett]
Code:
if not Programming = 'Severe Migraine' then
                       ShowMessage('Eureka!');
 
OH wait, now I get it! You are looking for:

Self.Free;

[bobafett] BobbaFet [bobafett]
Code:
if not Programming = 'Severe Migraine' then
                       ShowMessage('Eureka!');
 
Yes, this was same I try first, but...
Something is wrong, because when after
Self.Free; // or Self := nil; (what is actually Form2 := nil)

I check this condition:
if not Assigned(Form2) then
...

program behave like Form2 IS NOT NIL!?!?!?

BobaFet, Thanks anyway!
 
When you free a pointer to an object the variable, Form2 in this case, still points to something - there's just nothing there. So your variable isn't nil.

I don't quite understand your original question but to free and nil a pointer you can call FreeAndNil(Form2); and that will make it all tidy and clean.
 
It seems there's confusion. When you do an object, you're not saying anything as it relates to the thing you are inheriting when it comes to code.

What you are saying, though, is that a descendant object has the same properties as the inherited object. This is how your average form definition works in the first place.

Code:
TForm1 = class(TForm)

This is saying that TForm1 is a descendant object of TForm, which is defined in the forms unit. Now what happens is that I can add or alter things by how I define TForm1.

Now when I work with TForm1, I don't need to have any concern with dealing with the things TForm defines, since if the programmer did a decent job, I shouldn't have to worry about doing anything to that code, just use it.

Now if I create this object, all I need to do is free this object. This happens automatically, but if it doesn't, all I need to do is Form1.Free; and I don't have to worry about anything related to TForm.

Clearer?

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
My intention is to Free and nil anyone of DESCENDANT Forms (TForm2 = class(TForm1), TForm3 = class(TForm2),...) trough Form1.FormClose procedure:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:= caFree;
Form1 := nil;

// or, maybe like DjangMan says, just: FreeAndNil(Form1);
end;

So, should I replace 'Form1' in this procedure to achieve this goal (and with what?), or not?
 
I guess there is the difference between a descendant of a form and the owner of a form.

Form1 = Class(TForm);

Form2 = Class(TForm1);

If Form1 is created automatically when you run the application but Form2 is created at runtime - when you create Form2 you have to specify an owner (or nil). If your Form2 is owned by Form1 then Form2 will be freed when Form1 is destroyed. You could do it manually by going through the .components of Form1 and free anything that is of type TForm2. TForm2 could do the same to clear out any TForm3 children.

Code:
for i:=0 to Self.ComponentCount-1 do
    if Self.components[i] is TForm2 then
    begin
        TForm2(application.components[i]).Free;
    end;

If you have one Form1 variable and have opened several instances of Form2 - and Form1 doesn't own any of the Form2 then you'll need to sweep through the forms of your application to identify which forms are of type TForm2 so you can close them.
 
My intention is to Free and nil anyone of DESCENDANT Forms (TForm2 = class(TForm1), TForm3 = class(TForm2),...) trough Form1.FormClose procedure:

And the idea of OOP doesn't make that possible.

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
I'm guessing Delphard is confusing inheritance with an owned form, that is, a form that is owned by a parent form.

If you define a form (eg. TForm1), and add components to it (buttons, edit boxes etc), then inherit a new class from it (eg. TForm2 = class(TForm1), then TForm2 will contain copies of everything, including components, of TForm1.

Generally, for programs with a static UI structure, you don't do any sort of inheritance of forms to other forms.

What it sounds like what you want to do is have a master form, that spawns other different forms, that may in themselves spawn other different forms. And you want to be able to say TopLevelForm.Close and have all of the other forms it spawned close as well.

If this is the case, then just call ChildForm.Close in each form's OnClose event, and they'll all close.

There's a difference between freeing a form, and simply closing a form (which just hides it). Unless you're really concerned about conserving memory, closing your forms, and then showing them again is fine. Let the application manage auto-creating and freeing all of your forms.
 

One more attempt:

I make 'generic' Form (GForm) and put them into Delphi Repository (so I DON'T create GForm in my Project, I just use them to INHERIT other forms!).

GForm is ancestor for several forms in my Project: XForm, YForm, ZForm,... (all of them are created from Repository, inheriting GForm)
Code:
TXForm = class(TGForm)
...

also:
Code:
TYForm = class(TGForm)
...

Is it possible to define OnClose method in GForm, so that all od descendant forms (XForm, YForm, ZForm,...) will automatically execute that code in their OnClose event (without re-writing that code in XForm.OnClose, YForm.OnClose, ZForm.OnClose)?

I cant say this simplier...

 
I don't have Delphi up and running but this should be pretty close:

Code:
for i:=0 to Application.ComponentCount-1 do
    if Application.components[i] is TGForm then
    begin
        TGForm(application.components[i]).Free;
    end;
 
I don't want to Free ALL FORMS of TGForm Type when one of them is Closed, but exactly that one!
 
Ah - I see.

So you have code on OnClose for TGForm and when you close TXForm you want that code to be called.

I think you can simply put the inherited in the OnClose of your TXForm. Any code that TXForm needs to call first can be coded before the call to inherited.
 
Yes, exactly that!

All that I knew before, just don't know:

WHAT CODE to put in on OnClose for TGForm so that code will be recognize which exactly form is calling them - TXForm or TYForm or TZForm or... and Close that form?
 
Is that because you want TGForm to know how to handle the specifics of closing TXForm, TYForm and TZForm?
 
No, there is nothing specific in closing any of TXForm, TYForm and TZForm forms! I just want to avoid duplicating actually same code on all of descending forms in their OnClose event.
So, if possible, one code on TGForm that will close any (so, NOT ALL, but just concrete one!) descendant form.
 
When you write code for TGForm in OnClose it's descendants will automatically call it.

I created a form: TForm16. Saved in this unit:
Code:
unit Unit16;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm16 = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form16: TForm16;

implementation

{$R *.dfm}

procedure TForm16.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    ShowMessage('Closed Tform16');
end;
end.

I created a new project, included Unit16 in my uses, redeclared the form as a TForm16. That unit is as follows:
Code:
unit Unit17;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Unit16;

type
  TForm17 = class(TForm16)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form17: TForm17;

implementation

{$R *.dfm}

end.

I start the project and close the form and see my message box saying "Closed Tform16".

Notice that TForm17 doesn't have any code in OnClose at all.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top