I am attempting to create two identical objects in VB6 by assignment statements; something like this...
Dim myobj1 As Class1 Dim myobj2 As Class1 Set myobj1 = New Class1 myobj1.myval = 1 Set myobj2 = myobj1
It has become apparent that this doesn't create two objects but rather two references to the same object, which isn't what I am after. Is there any way to create a second object in this sort of way, or do I have to copy the object one member at a time...
Set myobj2 = new Class1 myobj2.mem1 = myobj1.mem1 ...
?
Edit 2 Scott Whitlock has updated his excellent answer and I have incorporated his changes into this now-working code snippet.
Private Type MyMemento Value1 As Integer Value2 As String End Type Private Memento As MyMemento Public Property Let myval(ByVal newval As Integer) Memento.Value1 = newval End Property Public Property Get myval() As Integer myval = Memento.Value1 End Property Friend Property Let SetMemento(new_memento As MyMemento) Memento = new_memento End Property Public Function Copy() As Class1 Dim Result As Class1 Set Result = New Class1 Result.SetMemento = Memento Set Copy = Result End Function
One then performs the assignment in the code thus...
Set mysecondobj = myfirstobj.Copy
An object is a combination of code and data that can be treated as a unit. An object can be a piece of an application, like a control or a form. An entire application can also be an object.
You assign an object to such a variable by placing the object after the equal sign ( = ) in an assignment statement or initialization clause.
You can assign an existing object reference to another variable using the Set statement without the New keyword. An assignment using Set does not copy an object. The assigned value is a reference to an object, not the object itself.
Like many modern languages, VB6 has value types and reference types. Classes define reference types. On the other hand, your basic types like Integer
are value types.
The basic difference is in assignment:
Dim a as Integer Dim b as Integer a = 2 b = a a = 1
The result is that a
is 1 and b
is 2. That's because assignment in value types makes a copy. That's because each variable has space allocated for the value on the stack (in the case of VB6, an Integer takes up 2 bytes on the stack).
For classes, it works differently:
Dim a as MyClass Dim b as MyClass Set a = New MyClass a.Value1 = 2 Set b = a a.Value1 = 1
The result is that both a.Value1
and b.Value1
are 1. That's because the state of the object is stored in the heap, not on the stack. Only the reference to the object is stored on the stack, so Set b = a
overwrites the reference. Interestingly, VB6 is explicit about this by forcing you to use the Set
keyword. Most other modern languages don't require this.
Now, you can create your own value types (in VB6 they're called User Defined Types, but in most other languages they're called structs or structures). Here's a tutorial.
The differences between a class and a user defined type (aside from a class being a reference type and a UDT being a value type) is that a class can contain behaviors (methods and properties) where a UDT cannot. If you're just looking for a record-type class, then a UDT may be your solution.
You can use a mix of these techniques. Let's say you need a Class because you have certain behaviors and calculations that you want to include along with the data. You can use the memento pattern to hold the state of an object inside of a UDT:
Type MyMemento Value1 As Integer Value2 As String End Type
In your class, make sure that all your internal state is stored inside a private member of type MyMemento
. Write your properties and methods so they only use data in that one private member variable.
Now making a copy of your object is simple. Just write a new method on your class called Copy()
that returns a new instance of your class and initialize it with a copy of its own memento:
Private Memento As MyMemento Friend Sub SetMemento(NewMemento As MyMemento) Memento = NewMemento End Sub Public Function Copy() as MyClass Dim Result as MyClass Set Result = new MyClass Call Result.SetMemento(Memento) Set Copy = Result End Function
The Friend
only hides it from stuff outside your project, so it doesn't do much to hide the SetMemento
sub, but it's all you can do with VB6.
HTH
@Scott Whitlock, I was not able to make your code work but if it works it would be great.
I've created a regular module where I put the memento type
Type MyMemento Value1 As Integer Value2 As String End Type
Then I create a class module called MyClass with the code
Private Memento As MyMemento Friend Sub SetMemento(NewMemento As MyMemento) Memento = NewMemento End Sub Public Function Copy() as MyClass Dim Result as MyClass Set Result = new MyClass Result.SetMemento(Memento) Set Copy = Result End Function
Finally I try to call the copy function in another regular module like this
Sub Pruebas() Dim Primero As MyClass, segundo As MyClass Set Primero = New MyClass Set segundo = New MyClass Set segundo = Primero.Copy End Sub
I get the message (below the picture): Error de compilacion: El tipo de agumento de ByRef no coincide
Here is an image (short of 10 points so here is the link): http://i.stack.imgur.com/KPdBR.gif
I was not able to get the message in English, I live in Spain.
Would you be so kind to provide with an example in VBA Excel?, I have been really trying to make this work.
Thanks for your work
===============================================
The problem was on line "Result.SetMemento(Memento)", in VBA it needed to be called with "Call"
Public Function Copy() As MyClass Dim Result As MyClass Set Result = New MyClass Call Result.SetMemento(Memento) Set Copy = Result End Function
It works great, thanks Scott Whitlock, you are a genius
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With