PDA

View Full Version : Classes



chrisjones
07-30-2010, 06:41 AM
Every time I run my test method I get the following error "Run-time error '91' Object variable or With block variable not set"

What am I doing wrong



This is the test class to test my person class


Public Sub testClass()
Dim p As Person
Set p = New Person

Dim d As Details
Set d = New Details
Set p.Details = d

p.Details.Age = 20
p.Details.Name = "chris"
End Sub


This is the Person Class


Private pDetails As Details
Public Property Get Details() As Details
Details = pDetails
End Property

Public Property Set Details(value As Details)
pDetails = value
End Property



This is the Details class


Private pName As String
Private pAge As Integer

Public Property Get Name() As String
Name = pName
End Property

Public Property Get Age() As Integer
Name = pName
End Property

Public Property Let Name(ByVal value As String)
pName = value
End Property
Public Property Let Age(ByVal value As Integer)
pAge = value
End Property

Public Function toString() As String
toString = pName & "," & pAge
End Function


Thanks in advance

Chris

austenr
07-30-2010, 06:50 AM
You need a with block here (in red) i think

Public Sub testClass()
Dim p As Person
Set p = New Person

Dim d As Details
Set d = New Details
Set p.Details = d
With d
p.Details.Age = 20
p.Details.Name = "chris"
End with
End Sub

chrisjones
07-30-2010, 07:09 AM
No debug is saying it is failing on the line Set p.Details = d

austenr
07-30-2010, 07:14 AM
Thats probably because you defined the variable as private which makes it only accessable to that function/sub.

chrisjones
07-30-2010, 07:18 AM
yes but I have public get and set methods which I am using to acess the private object. Surely there is a better way to do this than declaring the object public?

Chris

austenr
07-30-2010, 07:19 AM
Also are you sure this line is correct:

Private pDetails As Details

If I copy your first bit of code into a module and debug it it errors on this line with the reason being"User defined type not defined"

chrisjones
07-30-2010, 07:22 AM
They need to go in class modules and you will need the Details class as well. Then it should be ok

mikerickson
07-30-2010, 07:57 AM
The object p.Details has not been instancised.

in the Person class, you need to intialize pDetails and use Set in the Property code.
Option Explicit

Private pDetails As Details

Public Property Get Details() As Details
Set Details = pDetails
End Property

Public Property Set Details(value As Details)
Set pDetails = value
End Property

Private Sub Class_Initialize()
Set pDetails = New Details
End Sub


Edit: Also, Person should have a Terminate event that sets pDetails = Nothing.

Bob Phillips
07-30-2010, 07:58 AM
You haven't loaded Details, so you will get an error. But why do you have Details and Person, seems superluous to me seeing as Person just points at Details.

chrisjones
07-30-2010, 08:18 AM
Great, its working now thnaks

Bob Phillips
07-30-2010, 09:10 AM
Would you still care to share with me why you are doing it this way. You have a calss with all of the properties, and another class that just wraps the first class. What is the point?

chrisjones
07-30-2010, 09:24 AM
The point was just purely learning. I just wanted to figure out how to encapsulate a custom object in a class.

Thanks for your help

mikerickson
07-30-2010, 11:06 AM
Actualy, my answer was incomplete.

In the OP, the keyword Set has to be added to the Details property routines
Public Property Get Details() As Details
Set Details = pDetails
End Property

Public Property Set Details(value As Details)
Set pDetails = value
End Property

But, the Class_Initialize event I posted above is not needed. Whether or not to initialize pDetails (i.e. Set pDetails = New Details) relates to Xld's question "Why"?

If the Object model is that each Person has its own Details, then the Person class should initialize pDetails.

If the model is that Details exist independent of People and that the connection between People and Details is only formal, then it might be best not to initialize Details in the People class module.

Consider Age. An Age = 3 years doesn't make sense. Age of what? Logically, Age can't be a stand alone object. The Object pAge should be initialized inside Person's class module

Compare House. A House as an independent object makes sense. In an object model that allows one to say somePerson.House = thatHouse, it would be best if pHouse was initialized outside of the Person Class module

If an ObjectA only makes sense if it is the a property of some ObjectB, then initializing ObjectA should take place inside ObjectB's code module.

If an ObjectA makes sense independent of any ObjectB, then it might be better if initializing ObjectA and setting its properties outside of ObjectB's class module.