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 SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

PUBLIC, PRIVATE & LOCAL

Status
Not open for further replies.

IRABYY

Programmer
Apr 18, 2002
221
0
0
US
I am starting this thread by suggestion from Mike Lewis.

My statement:

PRIVATE mem. vars. belong to a class definition. For everything else there are LOCAl and PUBLIC mem. vars. And the less PUBLIC mem. vars. - the better.

Consequently, implicit memory variable's declaration - which makes it PRIVATE - in procedural modules has to be avoided. (This includes implementation of SCATTER MEMVAR command in procedure and/or function as well.)

Everybody is welcome to join the discussion.


Regards,

Ilya
 
Well, this thread is getting a little deeper into this topic than I think it was originally intended. However, having said that ...

Let's dig a little deeper ...

I was thinking about how these various variable types are actually implemented and I think I once knew this.

However, now I do not have a clear understanding of this.

I believe that LOCAL variables are placed on a STACK and then the stack pointer is reset when exiting from the function or procedure. This results in the LOCAL variable values being completely lost.

But the PRIVATE variables are not as simple. The PUBLIC ones also are not clear to me.

Anyone care to take a crack at the actual IMPLEMENTATION of these variable types ?



Don


 
HarryB (Programmer):
why not create an object in your root program, then add
properties to it when/as needed, and refer to them as
MyObject.Variable1, etc.?

Agreed 100% when custom class is to be used. But we are
talking here about conventional procedures and functions in
procedural modules.
Good point, though! I'm gonna give it serious consideration
for future projects. Thanks for the tip, bro!

MikeLewis (Programmer):
calling a menu from a method

Could you please elaborate? For instance: "method" - is it
method in a custom class you define in your program?
Or "menu" - is it modified system menu or, again, defined
in a procedure with DEFINE commands?

As for my own experience, I do have to declare PUBLIC
mem.vars. - sometimes even on a fly - for holding the
reference for the form I instantiate. But then - I have a
small procedure LaunchForm(). Say, I put

PUBLIC frmMain

somewhere in the beginning of the Main procedure,
and later

= LaunchForm("frmMain")

where
Code:
******************************************************************
PROCEDURE LaunchForm(tcFormName)
******************************************************************
** Function Name : Launch Form
** Purpose       : Launches the form for the selected utility.
** Description   : 
** Parameter(s)  : 
** Side Effect(s): 
** Notes:        : ControlExist() - function I wrote to
**                 check the existence of a control in ? on
**                 a given form.
******************************************************************
IF TYPE('tcFormName') # "C"  && Means close all forms
   tcFormName = ""
ENDIF
tcFormName = ALLTRIM(tcFormName)

LOCAL lcFormName, lcFileName, loForm, llFormRuns

lcFileName = JUSTFNAME(tcFormName)
lcFormName = JUSTSTEM(lcFileName)

IF EMPTY(JUSTEXT(lcFileName))
   lcFileName = lcFileName + ".SCX"
ENDIF

llFormRuns = .F.

FOR EACH loForm IN _SCREEN.Forms
   IF EMPTY(lcFormName) .OR. (lcFormName # loForm.Name)
      DO CASE
      CASE ControlExist(loForm, "cdmBar")
         loForm.cmdBar.Exit.Click
      CASE ControlExist(loForm, "cmdExit")
         loForm.cmdExit.Click
      OTHERWISE
         RELEASE WINDOW (lcFormName)
      ENDCASE
   ELSE
      llFormRuns = .T.
   ENDIF
NEXT

IF !llFormRuns .AND. !EMPTY(lcFormName)
   DO FORM (lcFileName) NAME (lcFormName)
ENDIF

ENDPROC
Note that evern though I declared the form name as PUBLIC, I still pass it as a local parameter to the above procedure.
Thus, later on, I can reference to my Main form by frmMain,
which is also the FORM.Name property's value.

Now, I can put as a command for the pad in my bar menu

= LaunchForm("frmMain.SCX")

and then, in any place else, something like

frmMain.grdIndex.clmIndex.ControlSource = "blablabla"


Regards,

Ilya
 
csr (Programmer):
I believe that LOCAL variables are placed on a STACK and then the stack pointer is reset when exiting from the function or procedure.

Yes, this is how it works in C. Since VFP is written in C/C++ (I presume) it should be true for VFP as well.

PUBLIC are also available in C (s./b. declared outside even Main() function, though).

As for PRIVATE - can't even guess how did they do that. Even if you place it in the heap memory with malloc() function - how it can be visible to the functions other than the one in which it was declared. Maybe VFP compiler handles that? Makes it "temporarily public" until the subroutine-originator exits? [ponder]


Regards,

Ilya
 
Ilya,

Could you please elaborate? For instance: "method" - is it method in a custom class you define in your program?
Or "menu" - is it modified system menu or, again, defined
in a procedure with DEFINE commands?


Let me give you an example. Let's say you want to pop up a context menu when the user right-clicks in an edit box. One of the bars in the menu might or might not be present, depending on the state of a property of the form.

Now, the menu code cannot directly interrogate the form property (it can't refer to THISFORM). So, in the RtClick method of the textbox, you declare a PRIVATE variable, then store the property in that variable. The menu can see the private variable and can act accordingly.

I admit that that is not a very common scenario, but it is one that I have faced recently. Also, the same applies to reports. A report might need to act in a certain way, depending on the state of a variable in the routine that calls the report. Again, the variable would have to be private.

Mike



Mike Lewis
Edinburgh, Scotland
 
Mike,

The variable would need to be 'in scope' - not necessarily PRIVATE (clearly a LOCAL would be no good) a PUBLIC variable would work just as well.

Martin



Regards

Griff
Keep [Smile]ing
 
HarryB and Ilya,

The question was raised about using properties of an object rather than public variables.

I agree completely with this. However, keep in mind that the object itself has to be referenced from a public variable.

Ilya, you talked about public variables to hold references to forms:
As for my own experience, I do have to declare PUBLIC
mem.vars. - sometimes even on a fly - for holding the
reference for the form I instantiate


One thing that I am strongly against is declaring public variables on the fly. That can cause big problems. If you are going to use public variables, declare them all explicitly at the top of the main program; also, use a naming convention to identify them.

Mike


Mike Lewis
Edinburgh, Scotland
 
Mike is right about declaring public variables on the fly so to speak - if you do that, they may not have been declared when you want to use them!

Regards

Griff
Keep [Smile]ing
 
Mike

'One thing that I am strongly against is declaring public variables on the fly.'

The only way I've ever found of keeping form object references in scope is by declaring the object reference PUBLIC, such as :-

PUBLIC oForm1
DO FORM form1 NAME oForm1

Equally I would suggest it's good practice to release the object reference when you release the form as 'dangling' object references may cause problems.

Having done so, you then need to run the above code again the next time you want to run that form.

It seems you have a simple choice - PUBLIC variable declarations on the fly or the risk of dangling object references?

I know which I prefer! [dazed]

FAQ184-2483 - the answer to getting answered.​
Chris [pc2]
 
Chris,


PUBLIC oForm1
DO FORM form1 NAME oForm1


My preferred route is to use my form manager class, which can provide an object reference to any open form on demand. Admittedly, it was more work to write it in the first place, but it solves that particular problem and many others.

Mike


Mike Lewis
Edinburgh, Scotland
 
Hi all !
May it's not good but i declare only public variables. But when i use forms i prefer properties.

Monika from Warszawa (Poland)
(monikai@yahoo.com)
 
Chris,

By 'form manager class', I assume you are referring to an object created in the root part of your main.prg?


Yes. It is a global object which any part of the app can call. And, yes, I store a reference to that object in a public variable.

Mike


Mike Lewis
Edinburgh, Scotland
 
Thought this might be helpful with the thread. Explains a little how Private Variables work.

From the "Hacker's Guide to VFP 7"

LOCAL and PUBLIC actually create variables—once you issue them, the variables actually exist, and early binding can take place. PRIVATE doesn't create variables—it reserves names—so if and when you create the variable, it becomes private. This difference has been tripping people up for years.

the Hacker's Guide also says to avoid PUBLIC variables. Instead use properties in an Application Object.

 
Everybody's made valid points.

Of course, extensive use of PUBLIC should be avoided (that's for you, Monika).

Of course, declaring PUBLIC mem. vars. may open a can of worms (Mike is right).

But if you are discrete and careful enough in using PUBLIC (and that comes with practice), then it can become a real breakthrough when you have to instantiate the same form more than once. That's what I had to do in my last major project. I designed a form to show a document's pages. "Document", BTW, may be a single page in a plain blue-bar GL-like report, or report is a set of statements/letters/etc. But this Data Screen for showing pages is always an instance of the same data Image form, "frmDatIm".
Now, when the page/doc is found in the database and ready to be "exposed" ( [smile] ) I do the following:
Code:
lcFrmName = WindowWithDocExists(lcDocAlias) && UDF returns empty str if it doesn't.
IF !EMPTY(lcFrmName)
   &lcFrmName..Visible = .T.
   &lcFrmName..WindowState = 0
   &lcFrmName..ZOrder(0)
   &lcFrmName..cmdBar.PageDn.SetFocus
ELSE
   lcFrmName = "frmDat_" + lcAppID + "_" + lcDocKey
(Mike! Note how I build the form's instance's name - speaking of naming conventions.)
Code:
   lcCommand = "PUBLIC " + lcFrmName
   &lcCommand
   lcCommand = "DO FORM 'frmDatIm.SCX' NAME " + ;
               lcFrmName + ;
               " WITH [" + lcDocAlias + "], [" + ;
               lcFrmName + ;
               "], [" + lcAppID + "], [" + lcDocKey + ;
               "], [" + .Name + "], [" + lcSrcValue + "]"
   &lcCommand
ENDIF
where lcAppID is the report ("Application") identifier, lcDocAlias is a recordset (SQL cursor) with the records containing doc's pages, lcSrcValue is the search (criterium) value for highlighting in the displayed page's text, and lcDocKey - well, that's selfexplanatory.

Of course, on the exit from that screen, I have to release that variable-pointer on the form object.

This technique has been working flawlessly for a year now, at many customers'. (Not that I'm trying to show off or pat myself on the back... [blush] )

So the point is - PUBLIC is OK as long as you keep a watchful eye on them. But PRIVATE - well, I dislike them (to put it mildly) and never use in PRGs.


Regards,

Ilya
 
MikeLewis (Programmer):
Let's say you want to pop up a context menu when the user right-clicks in an edit box. One of the bars in the menu might or might not be present, depending on the state of a property of the form.

Now, the menu code cannot directly interrogate the form property (it can't refer to THISFORM). So, in the RtClick method of the textbox, you declare a PRIVATE variable, then store the property in that variable. The menu can see the private variable and can act accordingly.

If I may suggest another scenario, Mike, I'd say:

You can always obtain that form's name in that txtEditBox.Click event procedure, i.e.

lcFrmName = THIS.Parent.Name

or even the reference to that form as an object itself, i.e.

loForm = THIS.Parent

Then you can pass lcFormName or loForm as a parameter to the routine that defines your popup.

Would that work for you?


Regards,

Ilya
 
Not necessarily Ilya, the textbox could be in a container like a pageframe..

So you would probably need to test or program for that.

Martin

Regards

Griff
Keep [Smile]ing
 
Hi

Well, I don't think it worked by putting it LOCAL becuase it still crashes.

It's weird.

It tells me that xx="JJAT" but it's impossible, the only thing I do to xx is concatinate to the end of it (and I do not use subs). All I do is say xx="JCAT"+"1" so my xx can NEVER equal to "JJAT"... What's going on.

It's gotta be a bug in vfp6 or something...

You guys helped me undertand the PUBLIC/LOCAL/PRIVATE thing and I thank you all but my prog still crashes randomly for no apperent reason.

PLEASE help
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top