Declaring before instantiating

tiredofit

Well-known Member
Joined
Apr 11, 2013
Messages
1,307
I'm not sure if the answer to my following question is the same as the answer to this thread:
Instantiating variables

so I'll ask it here.

This is ClsCar:

Code:
    Private varCar As clsMotorCars

Public Property Set Car(objCar As clsMotorCars)

    Set varCar = objCar

End Property

Public Property Get Car() As clsMotorCars

    Set Car = varCar

End Property

This is ClsMotorCars:

Code:
    Private strColor As String
    Private strName As String
    Private mG As Double

Property Let Color(clr As String)

    strColor = clr

End Property

Property Get Color() As String

    Color = strColor

End Property

Property Let Name(nm As String)

    strName = nm

End Property

Property Get Name() As String

    Name = strName

End Property

Property Let Mileage(milesGallon As Double)

    mG = milesGallon

End Property

Property Get Mileage() As Double

    Mileage = mG

End Property

Function FuelBudget(FuelCost As Double, Distance As Double) As Double

    FuelBudget = (Distance / Mileage) * FuelCost

End Function

This is in a standard module:

Code:
Sub propSetCars()

    Dim dist As Double
    Dim cost As Double

    Dim ownCar As clsCar
    Set ownCar = New clsCar


    '**************************************
    Set ownCar.Car = New clsMotorCars
    '**************************************

    ownCar.Car.Color = "Yellow"
    ownCar.Car.Name = "Ford"
    ownCar.Car.Mileage = 50

    dist = InputBox("Enter Distance in miles, covered by car in a month")
    cost = InputBox("Enter Cost of Fuel per gallon")

    MsgBox "Car Color is " & ownCar.Car.Color
    MsgBox "Car Model is " & ownCar.Car.Name
    MsgBox "Gives a Mileage of " & ownCar.Car.Mileage & " miles per gallon"

    MsgBox "$" & ownCar.Car.FuelBudget(dist, cost) & " is the monthly cost of fuel"

End Sub


I have two questions:

1. I am uncomfortable with this line of code:

Code:
    '**************************************
    Set ownCar.Car = New clsMotorCars
    '**************************************

in that I expected to see something like this first:

Code:
Dim owncar.Car = clsMotorCars

ie declaring before instantiating.

2. The function FuelBudget takes two arguments and consists of three components:

Code:
Function FuelBudget(FuelCost As Double, Distance As Double) As Double

    FuelBudget = (Distance / Mileage) * FuelCost

End Function

namely FuelCost, Distance and Mileage, wouldn't it be better to create FuelCost and Distance properties instead of passing them as arguments, or is that just a matter of choice?

Also, is this an example of composition, ie class relating to another class?

Thanks
 

Some videos you may like

Excel Facts

Remove leading & trailing spaces
Save as CSV to remove all leading and trailing spaces. It is faster than using TRIM().

Domenic

MrExcel MVP
Joined
Mar 10, 2004
Messages
19,383
1. I am uncomfortable with this line of code:

Code:
    '**************************************
    Set ownCar.Car = New clsMotorCars
    '**************************************

It's fine. First, a new instance of clsMotorCars is created. Then, using the property procedure Car, the newly created object is assigned to the member variable varCar, which has been declared as clsMotorCars and, therefore, capable of holding a reference to an object of that type.

As an example, though, if you wanted to, you could have done the same thing this way...

VBA Code:
    Dim newMotorCar As clsMotorCars
    Set newMotorCar = New clsMotorCars
    
    Set ownCar.Car = newMotorCar

    ownCar.Car.Color = "Yellow"
    ownCar.Car.Name = "Ford"
    ownCar.Car.Mileage = 50


Or, even this way...

VBA Code:
    Dim newMotorCar As clsMotorCars
    Set newMotorCar = New clsMotorCars
    
    newMotorCar.Color = "Yellow"
    newMotorCar.Name = "Ford"
    newMotorCar.Mileage = 50
    
    Set ownCar.Car = newMotorCar

2. The function FuelBudget takes two arguments and consists of three components:

Code:
Function FuelBudget(FuelCost As Double, Distance As Double) As Double

    FuelBudget = (Distance / Mileage) * FuelCost

End Function

namely FuelCost, Distance and Mileage, wouldn't it be better to create FuelCost and Distance properties instead of passing them as arguments, or is that just a matter of choice?

It's probably more a matter of being practical than a matter of preference.

For example, let's say that each month you receive a file containing data that includes FuelCost and Distance, and that you'll need to prepare various reports.

In this case, it would make sense to include properties for both FuelCost and Distance. This way, you would be able to read and parse the file so that all values could be assigned to their respective properties, etc.

Also, is this an example of composition, ie class relating to another class?

Have a look at the following link...


Hope this helps!
 

tiredofit

Well-known Member
Joined
Apr 11, 2013
Messages
1,307
It's fine. First, a new instance of clsMotorCars is created. Then, using the property procedure Car, the newly created object is assigned to the member variable varCar, which has been declared as clsMotorCars and, therefore, capable of holding a reference to an object of that type.

As an example, though, if you wanted to, you could have done the same thing this way...

VBA Code:
    Dim newMotorCar As clsMotorCars
    Set newMotorCar = New clsMotorCars
   
    Set ownCar.Car = newMotorCar

    ownCar.Car.Color = "Yellow"
    ownCar.Car.Name = "Ford"
    ownCar.Car.Mileage = 50


Or, even this way...

VBA Code:
    Dim newMotorCar As clsMotorCars
    Set newMotorCar = New clsMotorCars
   
    newMotorCar.Color = "Yellow"
    newMotorCar.Name = "Ford"
    newMotorCar.Mileage = 50
   
    Set ownCar.Car = newMotorCar



It's probably more a matter of being practical than a matter of preference.

For example, let's say that each month you receive a file containing data that includes FuelCost and Distance, and that you'll need to prepare various reports.

In this case, it would make sense to include properties for both FuelCost and Distance. This way, you would be able to read and parse the file so that all values could be assigned to their respective properties, etc.



Have a look at the following link...


Hope this helps!

Thanks for your explanantion. Your two examples are the way I would approach it.

I do have a query re your very first line.

Code:
It's fine. First, a new instance of clsMotorCars is created.

Which line (in the code I uploaded) creates a new instance of clsMotorCars?

Was it through these two lines:

Code:
Dim ownCar As clsCar
Set ownCar = New clsCar

because Car is of type clsMotorCars?
 

Domenic

MrExcel MVP
Joined
Mar 10, 2004
Messages
19,383
It's this one, the one that you had concerns with...

VBA Code:
Set ownCar.Car = New clsMotorCars

New clsMotorCars creates a new instance of the object clsMotorCars. Then this new object is passed to the property procedure Car belonging to the object ownCar. And then the property procedure Car assigns the passed in object to the private member variable varCar, which is declared as clsMotorsCars.
 

tiredofit

Well-known Member
Joined
Apr 11, 2013
Messages
1,307

ADVERTISEMENT

It's this one, the one that you had concerns with...

VBA Code:
Set ownCar.Car = New clsMotorCars

New clsMotorCars creates a new instance of the object clsMotorCars. Then this new object is passed to the property procedure Car belonging to the object ownCar. And then the property procedure Car assigns the passed in object to the private member variable varCar, which is declared as clsMotorsCars.

Thanks for the clarification.

That's why I am puzzled.

I was of the understanding to instantiate, you first have to write:

Code:
Dim something

so in this case, I expected to see:

Code:
Dim OwnCar As something

before:

Code:
Set something
 

Domenic

MrExcel MVP
Joined
Mar 10, 2004
Messages
19,383
Yeah, I know, it can be a bit confusing.

But a variable has already been declared to which an instance of clsMotorCars can be assigned. The private member variable varCar is declared as clsMotorCars and assigned the new instance of clsMotorCars.

So, as you can see, you can either declare a variable and assign a new instance of the object the way you're thinking of doing it...

VBA Code:
Dim newMotorCars as clsMotorCars
Set newMotorCars = New clsMotorCars

Or, you can create the new instance, and then pass it to a procedure so that it can be assigned to a variable that has been declared as clsMotorCars, the way your original code is doing it...

VBA Code:
Set ownCar.Car = New clsMotorCars

Think of it this way, New clsMotorCars creates the new object, and it's this new object that is passed to the procedure. The procedure here is the property procedure Car that belongs to the class object ownCar.

Here's another way of looking at it (not that I'm suggesting to do it this way, this is purely for illustration purposes)...

VBA Code:
Sub MySub(obj As clsMotorCars)
    'etc
    '
    '
End Sub

Sub test()

    Call MySub(New clsMotorCars)

End Sub

So, in this example, you can see that MySub() contains the parameter obj, which is declared as clsMotorCars. And, so it can accept a clsMotorCars object. In other words, you can assign it a clsMotorCars object, whether it's an existing object or a new object.

Now, in the procedure test(), first New clsMotorCars creates a new instance of the object clsMotorCars, and then MySub() is called with this new object passed to it.

And, when MySub() gets called, the variable obj gets assigned that new object. You can think of it this way...

VBA Code:
Set obj = New clsMotorCars

Hopefully this helps!
 

tiredofit

Well-known Member
Joined
Apr 11, 2013
Messages
1,307
Yeah, I know, it can be a bit confusing.

But a variable has already been declared to which an instance of clsMotorCars can be assigned. The private member variable varCar is declared as clsMotorCars and assigned the new instance of clsMotorCars.

So, as you can see, you can either declare a variable and assign a new instance of the object the way you're thinking of doing it...

VBA Code:
Dim newMotorCars as clsMotorCars
Set newMotorCars = New clsMotorCars

Or, you can create the new instance, and then pass it to a procedure so that it can be assigned to a variable that has been declared as clsMotorCars, the way your original code is doing it...

VBA Code:
Set ownCar.Car = New clsMotorCars

Think of it this way, New clsMotorCars creates the new object, and it's this new object that is passed to the procedure. The procedure here is the property procedure Car that belongs to the class object ownCar.

Here's another way of looking at it (not that I'm suggesting to do it this way, this is purely for illustration purposes)...

VBA Code:
Sub MySub(obj As clsMotorCars)
    'etc
    '
    '
End Sub

Sub test()

    Call MySub(New clsMotorCars)

End Sub

So, in this example, you can see that MySub() contains the parameter obj, which is declared as clsMotorCars. And, so it can accept a clsMotorCars object. In other words, you can assign it a clsMotorCars object, whether it's an existing object or a new object.

Now, in the procedure test(), first New clsMotorCars creates a new instance of the object clsMotorCars, and then MySub() is called with this new object passed to it.

And, when MySub() gets called, the variable obj gets assigned that new object. You can think of it this way...

VBA Code:
Set obj = New clsMotorCars

Hopefully this helps!

Thanks for your detailed answer.

If I were writing it from scratch, I'd follow your two suggestions rather than the original code but it's nice to understand what's going on.
 

Watch MrExcel Video

Forum statistics

Threads
1,114,188
Messages
5,546,467
Members
410,741
Latest member
Count25
Top