Class Scope

J

JimS

I developed a class module in A2007. As I went along, I would instantiate it
each time I needed it ("dim oBoM as new clsBillofMaterial"), then set it to
nothing when I was done with it, typically at the beginning and end of an
event procedure. Then, I thought, "why re-instantiate it so often...why not
instantiate it in the opening declarations for a form where I might use it,
then use it as needed.

Well, I'm gettting all balled up in scope issues. Am I doing this right?
What's the approach?
 
J

JimBurke via AccessMonster.com

Make sure you have everything declared as public in the class module that
might be referenced anywhere outside of the class (I think - I'm not an OOP
expert). I would declare the class variable oBoM in a code module as public,
but without instantiating it, e.g.

dim oBoM as clsBillofMaterial

Actually if you only use it within that one form then you can declare the
variable as private in that form's code module (at the very top of it). If
you need to access it anywhere outside that form then declare it as public in
a separate code module.

then wherever you want to instantiate it just set it:

set oBoM = new clsBillofMaterial

and set it to nothing as soon as you know you're done with it. without
knowing anything about your application or how the class is used I don't know
if you can just instantiate it once and keep using that, or when you might
have to declare a new instance, etc.
 
J

Jack Leach

Stephen Lebans has a calendar class that is set on form opening and unloaded
on form closing. Here's a link to the site, which at about 3/4 the way down
the page explains where to put the various calls and declarations to have it
work (the class is loaded on form load and unloaded on the form's unload).

http://www.lebans.com/monthcalendar.htm

Here's a very condensed version:


Option Compare Database
Option Explicit

'Declare the Class
Private mc As clsMonthCal

'the form's Load event
Private Sub Form_Load()
Set mc = New clsMonthCal
End Sub

'the form's unload event (minus some safeguards...)
Private Sub Form_Unload(Cancel As Integer)
Set mc = Nothing
End Sub


Then call mc.whatever from anywhere in the form you want to use it.

hth


--
Jack Leach
www.tristatemachine.com

"I haven't failed, I've found ten thousand ways that don't work."
-Thomas Edison (1847-1931)
 
J

JimBurke via AccessMonster.com

Whoops, where I put 'dim' meant 'public'.
Make sure you have everything declared as public in the class module that
might be referenced anywhere outside of the class (I think - I'm not an OOP
expert). I would declare the class variable oBoM in a code module as public,
but without instantiating it, e.g.

dim oBoM as clsBillofMaterial

Actually if you only use it within that one form then you can declare the
variable as private in that form's code module (at the very top of it). If
you need to access it anywhere outside that form then declare it as public in
a separate code module.

then wherever you want to instantiate it just set it:

set oBoM = new clsBillofMaterial

and set it to nothing as soon as you know you're done with it. without
knowing anything about your application or how the class is used I don't know
if you can just instantiate it once and keep using that, or when you might
have to declare a new instance, etc.
I developed a class module in A2007. As I went along, I would instantiate it
each time I needed it ("dim oBoM as new clsBillofMaterial"), then set it to
[quoted text clipped - 5 lines]
Well, I'm gettting all balled up in scope issues. Am I doing this right?
What's the approach?
 
A

Albert D. Kallal

JimS said:
I developed a class module in A2007. As I went along, I would instantiate
it
each time I needed it ("dim oBoM as new clsBillofMaterial"), then set it
to
nothing when I was done with it, typically at the beginning and end of an
event procedure. Then, I thought, "why re-instantiate it so often...why
not
instantiate it in the opening declarations for a form where I might use
it,
then use it as needed.

Well, I'm gettting all balled up in scope issues. Am I doing this right?
What's the approach?

I usually create and setup the class object in the forms load event.

However, often that object needs to be used in the next several forms that
will be opened.

So, you often see the following in my code:


clsBookInfo.MyClear ' setup class object
DoCmd.OpenForm "frmCalenderMain",,,,,,"Select date for event booking"

In form CalendarMain, you see in the defs:

Option Compare Database
Option Explicit

Public clsBookInfo As clsBooking
Dim frmPrevious As Form

Note how there is no new keyword used. I not going to instantiate a new
copy,
but I want the class object from the previous CALLING form.

So, my on-load code goes:


Set frmPrevious = Screen.ActiveForm
Set clsBookInfo = frmPrevious.clsBookInfo

Note how I now have a pointer to the previous class ojbect. Also, as a
codeing standard, I also pick up the previous form as per above. That way, I
cna have many differnt forms call this form, but on a close event I can go:

frmPrevious.Requery, etc.

In other words, I can access the prevous form as a varible.

And, when this form closes, all of the setup and use of the clbBookInfo
object is returned to the privous calling form. My applcaions will often go
2, 3 or even 4 forms deep using the above concepts... When the use finally
is done and starts closing the forms to get back where they came from, that
class objects values return back along for hte ride.

On the form when being closed, I can now call/execute code in the calling
form like:

frmPrevious.SelDoneB
DoCmd.Close acForm, Me.Name

SelDoneB is custom code in the calling form that needs to be run when I am
closign the current form. The nice part about using this approach is that I
don't have to make the form dialog (it is model, but not dialog).

The above desing also allows for multiplile instances of a form to be
opended...and the correct code from the calling (prevous) form is run when
using the above approach.
 
J

JimS

Hard to believe, but the code that failed yesterday works perfectly today. I
think I need to do the "decompile/compact/recompiile" thing to fix this
damned thing. Thanks so much for your answers. I'll study them for future
reference.

--
Jim


JimBurke via AccessMonster.com said:
Whoops, where I put 'dim' meant 'public'.
Make sure you have everything declared as public in the class module that
might be referenced anywhere outside of the class (I think - I'm not an OOP
expert). I would declare the class variable oBoM in a code module as public,
but without instantiating it, e.g.

dim oBoM as clsBillofMaterial

Actually if you only use it within that one form then you can declare the
variable as private in that form's code module (at the very top of it). If
you need to access it anywhere outside that form then declare it as public in
a separate code module.

then wherever you want to instantiate it just set it:

set oBoM = new clsBillofMaterial

and set it to nothing as soon as you know you're done with it. without
knowing anything about your application or how the class is used I don't know
if you can just instantiate it once and keep using that, or when you might
have to declare a new instance, etc.
I developed a class module in A2007. As I went along, I would instantiate it
each time I needed it ("dim oBoM as new clsBillofMaterial"), then set it to
[quoted text clipped - 5 lines]
Well, I'm gettting all balled up in scope issues. Am I doing this right?
What's the approach?
 
V

vanderghast

The variable you dim from the class is still a variable, and although the
data it indirectly refers to does not live on the stack, it is still a
variable and you should use its scope as usual: if you need it withih many
place in the form, declare it at the form level, and instanciate it in an
event firing once (for the life of the form), or test for its Nothing-ness
before using it and if Nothing, instance it or raise an assert (as you
expected it to be not nothing). If you only need it inside a given
procedure, then define and instance it inside the procedure. It is generally
not required to set it to nothing, from the program using the class object:
the variable going out of scope, or having the variable being re-assigned by
another object, will set the previous instance hold by the variable to
nothing for you.


Vanderghast, Access MVP
 
J

JimS

Well, I'm still having issues...
I decompiled and recompiled, etc. per advice from another poster.
I get an error on the Me. filter= statement in btnAddNewNoM_Click() routine.
The error refers to oBoM as if it were uninstantiated. I trap it and
try to see a property of the class in the immediate window, and sure enough,
it's not there.

I have to believe this is some syntax issue.

' Start Code

Option Compare Database
Option Explicit
Dim HourlyRate As Currency
Dim NewBoMHeaderID As Long
Public oBoM As clsBillofMaterial

Private Sub btnAddEmpty_Click()
NewBoMHeaderID = oBoM.AddBoMHeader(Me.cbWOID)
Me.Filter = "tblBoM.BomID=" & NewBoMHeaderID
Me.FilterOn = True
Me.cbWOID.Requery
Me.cbWOID = ""
Me.tbWODesc = ""
End Sub

Private Sub btnAddNewBoM_Click()
Me.Filter = "BoMWOID=" & Me.cbWOID & " AND BoMSeq=0" &
CStr(oBoM.NextBoMSeq(Me.cbWOID))
DoCmd.OpenForm FormName:="popupCloneBoM", Openargs:=CStr(Me.cbWOID)

Me.FilterOn = True
End Sub

Private Sub btnDelete_Click()
oBoM.delete Me.BoMWOID, Me.BoMSeq
End Sub

Private Sub cbWOID_AfterUpdate()
Me.tbWODesc = Me.cbWOID.Column(2)
Me.tbWODesc.Requery
tbHourlyRate.Requery
Me.Filter = "BoMWOID=" & Me.cbWOID & " AND BoMSeq=0" & Me.cbWOID.Column(3)
Me.FilterOn = True
End Sub

Private Sub Form_BeforeUpdate(Cancel As Integer)
'Check here to make sure the new quantity is not less than the "picked"
quantity

End Sub

Private Sub Form_Close()
Set oBoM = Nothing
End Sub

Private Sub Form_Load()
HourlyRate = 0
Me.cbWOID = Me.cbWOID.ItemData(0)
Me.Filter = "BoMWOID=" & Me.cbWOID & " AND BoMSeq=0" & Me.cbWOID.Column(3)
Me.FilterOn = True
Me.tbWODesc = Me.cbWOID.Column(2)
End Sub

Private Sub Form_Open(Cancel As Integer)
Set oBoM = New clsBillofMaterial
End Sub
 
V

vanderghast

Your code defines the object oBoM at the form level (and being Public, can
be accessed by other VBA code, through the form object 'as if' it was some
new form property). If it is not required, leave it Private.

Your code created an objet oBoM in the form Open event, but does not seems
to initialize it. So, your object oBoM will have all its data set to default
values, unless your oBoM class Initialize event (in the code of
clsBillofmaterial class) does something to its internal data.

Add a break point at the line where your error occur, so just before the
error occurs. Then, once the code stops at the break point (and before
executing the line producing the error)

Check if Me.cbWOID has a not null value.

? Me.cbWOID IS NULL



if it is null, the method NextBoMSeq must have its first argument AS
VARIANT or AS OBJECT (preferably As Variant).
BUT your filter will be in error anyhow, since the concatenated strings
result will be something like:

"BoMWOID= AND BoMSeq=0"

which is not a valid filter (because ... BoMWOID is equal to ... what? )


Check if oBoM is NOT Nothing,

? oBoM IS Nothing


if it is nothing, you have to track where your code set it to nothing (since
the variable is public, that maybe from code living OUTSIDE your form; if
the object is private, only the code in your form, and in class
clsBillofMaterial, can set it to Nothing)

In the Locals window (View | Locals Window), check if your variable oBoM has
all the required properties/methods (and see if the values you can reach
make 'sense', if applicable).

In the immediate debug window, check if oBoM.NextBoMSeq(Me.cbWOID) returns
NOT a NULL value.

? oBoM.NextBoMSeq(Me.cbWOID) IS NULL

If it returns a NULL value, CSTR(Null) will err.
Also check it returns an integer.

? oBoM.NextBoMSeq(Me.cbWOID)

If it returns a string, then the filter become, after concatenation:

"BoMWOID= 44 AND BoMSeq = 0AAA"


as example, and the string has wrong delimiters, it should be:

"BoMWOID= 44 AND BoMSeq = '0AAA' "

or

"BoMWOID= 'B44' AND BoMSeq = '0AAA' "


as example (or something similar). Note that Me.cbWOID should return a
number, else your code need ALSO the proper delimiters for the value
filtering BoMWOID.


In the Immediate Debug Window, check if the concatenated strings result in
something valid for the filter:

? "BoMWOID=" & Me.cbWOID & " AND BoMSeq=0" &
CStr(oBoM.NextBoMSeq(Me.cbWOID))



Note that you can add a line in the Form_Open sub:

Private Sub Form_Open(Cancel As Integer)
Set oBoM = New clsBillofMaterial
Debug.Assert Not oBoM Is Nothing ' assume oBoM is not nothing
End Sub


since, after all, you Assert (assume) the object is not nothing, anymore, at
this point. You can also insert the same line of code as the first line of
code in btnAddNewBoM_Click( ), for the same reason.



And it can be that the problem is something else...



Vanderghast, Access MVP


JimS said:
Well, I'm still having issues...
I decompiled and recompiled, etc. per advice from another poster.
I get an error on the Me. filter= statement in btnAddNewNoM_Click()
routine.
The error refers to oBoM as if it were uninstantiated. I trap it and
try to see a property of the class in the immediate window, and sure
enough,
it's not there.

I have to believe this is some syntax issue.

' Start Code

Option Compare Database
Option Explicit
Dim HourlyRate As Currency
Dim NewBoMHeaderID As Long
Public oBoM As clsBillofMaterial

Private Sub btnAddEmpty_Click()
NewBoMHeaderID = oBoM.AddBoMHeader(Me.cbWOID)
Me.Filter = "tblBoM.BomID=" & NewBoMHeaderID
Me.FilterOn = True
Me.cbWOID.Requery
Me.cbWOID = ""
Me.tbWODesc = ""
End Sub

Private Sub btnAddNewBoM_Click()
Me.Filter = "BoMWOID=" & Me.cbWOID & " AND BoMSeq=0" &
CStr(oBoM.NextBoMSeq(Me.cbWOID))
DoCmd.OpenForm FormName:="popupCloneBoM", Openargs:=CStr(Me.cbWOID)

Me.FilterOn = True
End Sub

Private Sub btnDelete_Click()
oBoM.delete Me.BoMWOID, Me.BoMSeq
End Sub

Private Sub cbWOID_AfterUpdate()
Me.tbWODesc = Me.cbWOID.Column(2)
Me.tbWODesc.Requery
tbHourlyRate.Requery
Me.Filter = "BoMWOID=" & Me.cbWOID & " AND BoMSeq=0" &
Me.cbWOID.Column(3)
Me.FilterOn = True
End Sub

Private Sub Form_BeforeUpdate(Cancel As Integer)
'Check here to make sure the new quantity is not less than the "picked"
quantity

End Sub

Private Sub Form_Close()
Set oBoM = Nothing
End Sub

Private Sub Form_Load()
HourlyRate = 0
Me.cbWOID = Me.cbWOID.ItemData(0)
Me.Filter = "BoMWOID=" & Me.cbWOID & " AND BoMSeq=0" &
Me.cbWOID.Column(3)
Me.FilterOn = True
Me.tbWODesc = Me.cbWOID.Column(2)
End Sub

Private Sub Form_Open(Cancel As Integer)
Set oBoM = New clsBillofMaterial
End Sub
 
J

JimS

Thanks for the encouragement...

For what it's worth...my class has no initialization routine and no
termination routine (though I'm thinking of doing a debug.print "I've just
been instatiated"...

My class also has no properties, only events. For all intents and purposes,
it's a code module, but I wanted to practice class modules and I expect
eventually to add some properties and other goodies.

I'll run through your ideas and see what comes out...

Again, thanx!

Jim
 
J

JimBurke via AccessMonster.com

Like I said earlier, I'm no OOP expert, but is it realistic to ever have a
class that has no properties? What are the events supposed to be related to?
Seems like these would just be subs/functions in a regular code module if
they're not directly related to anything. Just curious - it seems like if you
want to practice with classes you would have an object that represents an
entity, and if there are no properites at all, how does it relate to any
specific entity? Maybe it's just been too long since I did anything with
objects. I can see having an object with properties and no methods (I've done
this, it really just represents a basic data structure), but not the opposite.

Thanks for the encouragement...

For what it's worth...my class has no initialization routine and no
termination routine (though I'm thinking of doing a debug.print "I've just
been instatiated"...

My class also has no properties, only events. For all intents and purposes,
it's a code module, but I wanted to practice class modules and I expect
eventually to add some properties and other goodies.

I'll run through your ideas and see what comes out...

Again, thanx!

Jim
Your code defines the object oBoM at the form level (and being Public, can
be accessed by other VBA code, through the form object 'as if' it was some
[quoted text clipped - 191 lines]
 
D

David W. Fenton

I developed a class module in A2007. As I went along, I would
instantiate it each time I needed it ("dim oBoM as new
clsBillofMaterial"), then set it to nothing when I was done with
it, typically at the beginning and end of an event procedure.
Then, I thought, "why re-instantiate it so often...why not
instantiate it in the opening declarations for a form where I
might use it, then use it as needed.

Well, I'm gettting all balled up in scope issues. Am I doing this
right? What's the approach?

Instantiate the object according to its necessary scope.

Yes, that's no answer!

Remember that if you re-use an existing instance, it will retain the
properties that have been set in its previous life. One way to make
that easy is to have a method that resets all the properties to
their default values.

I tend to use class modules to share data between multiple contexts,
so I generally don't instantiate them as I go along, so much as I
have a global instance that initializes itself the first time it's
used. It's then up to me to track what values need to be reset or
not.

With a global variable declaration of the type you've been using in
private contexts:

Public oBoM As New clsBillofMaterial

the easiest possible way to re-initialize it is simply:

Set oBoM = Nothing

....and then immediately start setting properties of the public
instance (which will re-initialize it without you needing to have
code that resets any of the properties or members of the class
module).

The answer to your question:

It depends!
 
D

David W. Fenton

I usually create and setup the class object in the forms load
event.

However, often that object needs to be used in the next several
forms that will be opened.

So, you often see the following in my code:

clsBookInfo.MyClear ' setup class object
DoCmd.OpenForm "frmCalenderMain",,,,,,"Select date for event
booking"

In form CalendarMain, you see in the defs:

Option Compare Database
Option Explicit

Public clsBookInfo As clsBooking
Dim frmPrevious As Form

Note how there is no new keyword used. I not going to instantiate
a new copy,
but I want the class object from the previous CALLING form.

But within the context of CalendarMain's class module, you'll be
using Forms!CalendarMain.clsBookInfo, which is not the same instance
as the one referred to in the line immediately before you open the
form CalendarMain. You have an overlap in terms of the name of your
class module instance's variable name.
So, my on-load code goes:

Set frmPrevious = Screen.ActiveForm
Set clsBookInfo = frmPrevious.clsBookInfo

Note how I now have a pointer to the previous class ojbect.

Now, that's a different story. In this case you're using the same
class instance, because it's a public member of the class module of
the other form, and you're assured that it's the same class
instance.

But in your original example, you operated on one instance of the
class module:

Instance 1: clsBookInfo.MyClear ' setup class object

Then opened a form:

DoCmd.OpenForm "frmCalenderMain", , , , , , _
"Select date for event booking"

And in that form's class module, initiated an entirely new instance
of the your base class:

Instance 2: Public clsBookInfo As clsBooking

This is because you have a local variable declaration in your
newly-opened form. If you want to use the same instance, then either
do what you said later (use an instance that is exposed as a public
member of another form's class module), or use an instance that is
defined as a public variable.

Quibbling aside in regard to your bollixed presentation of what you
are recommending, your approach is very good and quite useful.
 
D

David W. Fenton

The variable you dim from the class is still a variable, and
although the data it indirectly refers to does not live on the
stack, it is still a variable and you should use its scope as
usual: if you need it withih many place in the form, declare it at
the form level, and instanciate it in an event firing once (for
the life of the form),

If you're doing it at the form module level, just define your
variable with the New keyword and it will be automatically
instantiated the first time you use the variable.
or test for its Nothing-ness
before using it and if Nothing, instance it or raise an assert (as
you expected it to be not nothing). If you only need it inside a
given procedure, then define and instance it inside the procedure.
It is generally not required to set it to nothing, from the
program using the class object: the variable going out of scope,
or having the variable being re-assigned by another object, will
set the previous instance hold by the variable to nothing for you.

But if you're using a global instance as a way to pass information
among contexts, you may find a situation where you need to clear
everything to make sure that you're back to a clean state with the
class instance having its default values. Setting the global
instance to Nothing takes care of that.

That is, for a global instance (in a regular module) you have this
choice:

Public MyClass1 As New clsMyClass

The first time you use this variable, it will instantiate itself
automatically, and will be accessible in all code contexts. If you
need to start over with fresh data structures in your class
instance:

Set MyClass1 = Nothing

And then use it without needing to instantiate it.

Your other choice is to not depend on the New keyword to instantiate
it for you, and instead instantiate it as needed:

Public MyClass1 As clsMyClass

The first time you use it you have to instantiate it:

Set MyClass1 = New clsMyClass

Once that's done, it's no different than what I described above.

I generally prefer to have my class instances to be
self-instantiating, so I define their variables with the New
keyword, instead of initializing them when I use them.

The downside of that is that you may have to ask yourself in other
contexts if you want to use the values in the existing instance or
if you want to re-initialize. I'm not sure that either of these
approaches makes that easier, though.
 
D

David W. Fenton

Like I said earlier, I'm no OOP expert, but is it realistic to
ever have a class that has no properties?

My immediate response was to say NO, but then I gave it a little
thought and changed my mind to MAYBE.

These are the conditions that I think are the main determinants of
the answer to the question:

1. you're gathering together a group of functions/subs into a module

2. that group of functions/subs needs to share module-level
variables

3. you need to have different instances of this module with
different sets of values for the module-level variables.

If you don't meet those conditions, your class module should be a
plain old module.

However, it's a little strange to have the settings of the private
members of a class module done entirely through functions/subs. That
is, if you've got the shared module-level variables described in #2,
then if you have no Property Lets, then all those variables have to
have their values assigned by runnihg functions/subs in your (class)
module.

In general, the style of a class module is:

1. set some properties.

2. call a method that does something (or returns something) based on
those properties.

This is in contrast to the module approach in which you'd run some
subroutines or call some functions that in the course of being
called set certain internal "properties" to certain values.

In a certain sense, there's a logical equivalence between a Property
Get and a Function. Both return a single value based on code within
them. The difference, I think, is that the property should return an
atomic attribute of whatever is being modelled in your class, while
a function should return some kind of calculated information that is
derived from the attributes of the entity being modelled.

In short, properties in a class module are like the fields in a
table.

Functions in a class module are like calculated fields in a query.

Or, at least, so it seems to me upon giving it a first thought.

I'm sure the OO people probably have a bunch of theoretical
explanations of what the truth really is, of course.
 
D

David W. Fenton

Like I said earlier, I'm no OOP expert, but is it realistic to
ever have a class that has no properties?

My immediate response was to say NO, but then I gave it a little
thought and changed my mind to MAYBE.

These are the conditions that I think are the main determinants of
the answer to the question:

1. you're gathering together a group of functions/subs into a module

2. that group of functions/subs needs to share module-level
variables

3. you need to have different instances of this module with
different sets of values for the module-level variables.

If you don't meet those conditions, your class module should be a
plain old module.

However, it's a little strange to have the settings of the private
members of a class module done entirely through functions/subs. That
is, if you've got the shared module-level variables described in #2,
then if you have no Property Lets, then all those variables have to
have their values assigned by runnihg functions/subs in your (class)
module.

In general, the style of a class module is:

1. set some properties.

2. call a method that does something (or returns something) based on
those properties.

This is in contrast to the module approach in which you'd run some
subroutines or call some functions that in the course of being
called set certain internal "properties" to certain values.

In a certain sense, there's a logical equivalence between a Property
Get and a Function. Both return a single value based on code within
them. The difference, I think, is that the property should return an
atomic attribute of whatever is being modelled in your class, while
a function should return some kind of calculated information that is
derived from the attributes of the entity being modelled.

In short, properties in a class module are like the fields in a
table.

Functions in a class module are like calculated fields in a query.

Or, at least, so it seems to me upon giving it a first thought.

I'm sure the OO people probably have a bunch of theoretical
explanations of what the truth really is, of course.
 
J

JimS

OK, I can't defend a class module with no properties. I'm practicing. My goal
is to gather everything having to do with Bills of Materials into one class.
Ultimately, I'll have "count" properties, etc., but I don't need them yet. I
am still developing.

There must be something odd about my form because even though it's the only
active instantiation of the class, it just seems "flaky". Sometimes it works,
sometimes not. Most likely, since none of you found any syntax issues, I've
fouled up the form in other ways, and it's just manifesting itself this way.
I'll keep pluggin' away at it when I have time (client is actually paying for
this code....)

The last class I wrote (clsAuthenticate) worked flawlessly with both
properties and methods. I instantiated it once publicly in an opening
(hidden) form, and used its properties and methods in other forms with no
problem.

I have enjoyed all the discussions. Very enlightening!
 
A

Albert D. Kallal

And in that form's class module, initiated an entirely new instance
of the your base class:

Instance 2: Public clsBookInfo As clsBooking

This is because you have a local variable declaration in your
newly-opened form. If you want to use the same instance, then either
do what you said later (use an instance that is exposed as a public
member of another form's class module), or use an instance that is
defined as a public variable.

Actually, no...it is the same instance, and the initialize event does not
fire.

This is kind like when a person wants to add value fro a control on a form
and they
go:

colMydata.Add me.CompanyName

What actually gets added to the above collection is NOT the value of
companyname, but in fact the control object. To add the value, one needs to
use me.CompnayName.Value

In my case, if I want another instance of my class object, I have one of two
choices:

a) use the "new keyword" in its declare. Thus when I first reference the
object in code a new copy is created and it initialize event will fire..

b) use the set command with a "new" keyword eg:

eg:

clsObject = new ClsObject

Since I am only using a set command WITHOUT a new keyword, I windup with
ONLY pointer to the original object...not a 2nd copy in memory. Any change
to the object will be instanly avalbile to the 5 forms deep down that I am
currenly in the applciaon. In my exammple, the forms are model, but even if
they are not...all forms that modify that object will see the same values. I
am using Set without the the "new" keyword....so, you get a pointer to the
object...not a new instance...
 
V

vanderghast

If you see a 'structure' (or type def, in VBA), as a way to pack many
'parameters' under one 'variable', so instead of passing n-parameters to a
subroutine you just pass ONE variable, dim-ed as your typedef, then you can
also see the 'class' as a way to add specific code to handle the data
present in the 'structured' variable (and have the data presented
individually as data member, or properties, rather than exposed with a
typedef).

As 'simple' example, you can define a "car" as a type def wich will have a
brand name (string), a motor (may be itself another structure), four wheels,
.... but if you think that somehow those 'parts' may work in a specific way,
you can use a class instead of just the data in a typedef, and the brand
name, motor, wheels will become the properties (the data member) of the
class, and you can add code specific about what can be 'building' a car, or
'drawing' a car on a map, or what you mean when you 'compare' a car with
another, etc. And since that code follow your 'car'-data, in using class,
you don't have to remember to carry a module where those methods would have
otherwise been stored, probably what you would have to do using a typedef.

So, having a class without properties (or members) is, to continue the
analogy, like having code, without the 'typedef' built into the class. Such
classes can be useful, though, but, in VBA, they become limited and behaves
like a module where you still need an object of the said class to use the
procedures defined in the class, rather than just using the procedure,
directly, if the procedure comes from a module, and hoping there will be no
name collision.



Vanderghast, Access MVP


JimBurke via AccessMonster.com said:
Like I said earlier, I'm no OOP expert, but is it realistic to ever have a
class that has no properties? What are the events supposed to be related
to?
Seems like these would just be subs/functions in a regular code module if
they're not directly related to anything. Just curious - it seems like if
you
want to practice with classes you would have an object that represents an
entity, and if there are no properites at all, how does it relate to any
specific entity? Maybe it's just been too long since I did anything with
objects. I can see having an object with properties and no methods (I've
done
this, it really just represents a basic data structure), but not the
opposite.

Thanks for the encouragement...

For what it's worth...my class has no initialization routine and no
termination routine (though I'm thinking of doing a debug.print "I've just
been instatiated"...

My class also has no properties, only events. For all intents and
purposes,
it's a code module, but I wanted to practice class modules and I expect
eventually to add some properties and other goodies.

I'll run through your ideas and see what comes out...

Again, thanx!

Jim
Your code defines the object oBoM at the form level (and being Public,
can
be accessed by other VBA code, through the form object 'as if' it was
some
[quoted text clipped - 191 lines]
right?
What's the approach?
 
D

David W. Fenton

Actually, no...it is the same instance, and the initialize event
does not fire.

I cannot see how you can have a variable local to your form module
with the same name as a public variable and then have the local
variable refer to the public instance, unless you set it
accordingly. I don't see that you did that anywhere, and I don't see
any reason to have the form-level variable in the first place *if*
you want to use the instance that is being referred to with the
public variable.
This is kind like when a person wants to add value fro a control
on a form and they
go:

colMydata.Add me.CompanyName

What actually gets added to the above collection is NOT the value
of companyname, but in fact the control object. To add the value,
one needs to use me.CompnayName.Value

It's not the same at all, Albert.

If I have this:

Public lngInventoryID As Long

....in a standalone module and assign it a value in code anywhere:

lngInventoryID = 99

....and in MyForm's module, I have this:

Dim lngInventoryID As Long

....if I check the value of lngInventoryID in MyForm's module, it
will be 0 until such point as I've assigned a value to it.

Class module variables are no different -- local scope overrides
global scope.
In my case, if I want another instance of my class object, I have
one of two choices:

I thought you wanted to use the *same* instance?
a) use the "new keyword" in its declare. Thus when I first
reference the object in code a new copy is created and it
initialize event will fire..

b) use the set command with a "new" keyword eg:

eg:

clsObject = new ClsObject

Since I am only using a set command WITHOUT a new keyword, I
windup with ONLY pointer to the original object...not a 2nd copy
in memory. Any change to the object will be instanly avalbile to
the 5 forms deep down that I am currenly in the applciaon. In my
exammple, the forms are model, but even if they are not...all
forms that modify that object will see the same values. I am using
Set without the the "new" keyword....so, you get a pointer to the
object...not a new instance...

I understand what you're describing. Your post as written (and
explained above) does not support what you're trying to do.

Remember, I'm not talking about your form class, but about the other
one.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top