class - visual - Asignación de objetos en VB6
visual basic class (3)
o tengo que copiar el objeto un miembro a la vez ...
Por desgracia sí.
Es posible (pero técnicamente muy muy difícil) escribir un servidor COM en C ++ que, usando la interfaz IDispatch, copie el valor de cada propiedad, pero realmente esta es la programación de High Temple , si tuviera que hacerlo, no lo hago. t Sé si podría hacerlo, pero estaría buscando algo así como 10 días de trabajo (y sé cómo se implementa COM en C ++, también necesitaría investigar para ver si el marco ATL tiene algo para ayudar, etc.) .
Trabajé con Vb3, 4,5 y 6 durante algo así como 10 años (manos a la obra, 5 días a la semana) y nunca encontré una buena manera de hacerlo, más allá de implementar manualmente patrones de serialización como Mementos y Save & Store, que realmente solo hervían hasta formas sofisticadas de copiar cada miembro, uno a la vez.
Estoy intentando crear dos objetos idénticos en VB6 mediante declaraciones de asignación; algo como esto...
Dim myobj1 As Class1
Dim myobj2 As Class1
Set myobj1 = New Class1
myobj1.myval = 1
Set myobj2 = myobj1
Se ha vuelto aparente que esto no crea dos objetos sino dos referencias al mismo objeto, que no es lo que estoy buscando. ¿Hay alguna manera de crear un segundo objeto de esta manera, o tengo que copiar el objeto de a un miembro a la vez ...
Set myobj2 = new Class1
myobj2.mem1 = myobj1.mem1
...
?
Editar 2 Scott Whitlock ha actualizado su excelente respuesta y he incorporado sus cambios en este fragmento de código que ahora funciona.
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
Entonces uno realiza la asignación en el código así ...
Set mysecondobj = myfirstobj.Copy
@Scott Whitlock, no pude hacer que tu código funcionara, pero si funciona sería genial.
Creé un módulo regular donde pongo el tipo de recuerdo
Type MyMemento
Value1 As Integer
Value2 As String
End Type
Luego creo un módulo de clase llamado MyClass con el código
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
Finalmente trato de llamar a la función de copia en otro módulo regular como este
Sub Pruebas()
Dim Primero As MyClass, segundo As MyClass
Set Primero = New MyClass
Set segundo = New MyClass
Set segundo = Primero.Copy
End Sub
Aparece el mensaje (debajo de la imagen): Error de compilación: El tipo de aguante de ByRef no coincide
Aquí hay una imagen (menos de 10 puntos, así que aquí está el enlace): http://i.stack.imgur.com/KPdBR.gif
No pude obtener el mensaje en inglés, vivo en España.
¿Sería tan amable de proporcionar un ejemplo en VBA Excel ?, he estado tratando de hacer que esto funcione.
Gracias por tu trabajo
============================================
EDITAR: Problema resuelto:
El problema estaba en la línea "Result.SetMemento (Memento)", en VBA debía llamarse con "Llamar"
Public Function Copy() As MyClass
Dim Result As MyClass
Set Result = New MyClass
Call Result.SetMemento(Memento)
Set Copy = Result
End Function
Funciona muy bien, gracias Scott Whitlock, eres un genio
Al igual que muchos idiomas modernos, VB6 tiene tipos de valores y tipos de referencia. Las clases definen tipos de referencia. Por otro lado, sus tipos básicos como Integer
son tipos de valores.
La diferencia básica está en la asignación:
Dim a as Integer
Dim b as Integer
a = 2
b = a
a = 1
El resultado es que a
es 1 y b
es 2. Esto se debe a que la asignación en tipos de valor hace una copia. Esto se debe a que cada variable tiene espacio asignado para el valor en la pila (en el caso de VB6, un entero ocupa 2 bytes en la pila).
Para las clases, funciona de manera diferente:
Dim a as MyClass
Dim b as MyClass
Set a = New MyClass
a.Value1 = 2
Set b = a
a.Value1 = 1
El resultado es que tanto a.Value1
como b.Value1
son 1. Esto se debe a que el estado del objeto se almacena en el montón, no en la pila. Solo la referencia al objeto se almacena en la pila, por lo que Set b = a
sobrescribe la referencia. Curiosamente, VB6 es explícito al forzarlo a usar la palabra clave Set
. La mayoría de los otros idiomas modernos no requieren esto.
Ahora, puede crear sus propios tipos de valores (en VB6 se llaman Tipos definidos por el usuario, pero en la mayoría de los demás idiomas se denominan estructuras o estructuras). Aquí hay un tutorial .
Las diferencias entre una clase y un tipo definido por el usuario (aparte de que una clase sea un tipo de referencia y un UDT sea un tipo de valor) es que una clase puede contener comportamientos (métodos y propiedades) donde un UDT no puede. Si solo busca una clase de registro, entonces una UDT puede ser su solución.
Puedes usar una combinación de estas técnicas. Supongamos que necesita una Clase porque tiene ciertos comportamientos y cálculos que desea incluir junto con los datos. Puede usar el patrón de recuerdo para mantener el estado de un objeto dentro de un UDT:
Type MyMemento
Value1 As Integer
Value2 As String
End Type
En su clase, asegúrese de que todo su estado interno esté almacenado dentro de un miembro privado de tipo MyMemento
. Escriba sus propiedades y métodos para que solo utilicen datos en esa variable miembro privada.
Ahora hacer una copia de tu objeto es simple. Simplemente escriba un nuevo método en su clase llamado Copy()
que devuelva una nueva instancia de su clase e inicialícela con una copia de su propio recuerdo:
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
El Friend
solo lo oculta de las cosas que están fuera de tu proyecto, por lo que no sirve de mucho ocultar el sub de SetMemento
, pero es todo lo que puedes hacer con VB6.
HTH