|
Curso básico
de programación en Visual Basic
Lección
39
Clonar
objetos
|
Realizamos
programas para la gestión de empresas. Empresas medianas y
pequeñas. Programas de contabilidad, cartera de pedidos
clientes proveedores, facturación control de albaranes,
tesorería cartera de cobros y pagos y estadísticas.
Nuestro
agradecimiento a todos los que por unas causas o por otras
visitan nuestra web. Gestión de empresas PYMES. Curso de
programación de Visual Basic.
|
En la entrega
anterior te prometí que en esta ocasión íbamos a ver cómo crear
nuestras propias colecciones, pero, no va a ser así... como puedes
comprobar, algunas veces NO cumplo lo que digo... je, je, je, pero
no te preocupes que en la siguiente si que lo vamos a ver... es que
no es plan de que te acostumbres a tener todo lo que quieras...
Lo que vamos a
hacer es añadir más funcionalidad a la clase normal, y de paso
aprendes alguna que otra cosilla, o afianzas lo que ya has
aprendido, que de seguro no te vendrá mal.
¿Que podemos
añadirle?
Pues por ejemplo un método o función que permita hacer una
copia del objeto en cuestión.
Con esto, pretendo que comprendas que lo que estamos tratando o
manejando no es una "simple" variable, sino un objeto, que
como podrás comprobar, si no en estos ejemplos, si en otro código
que veas por ahí... ya que me imagino que no sólo te contentarás
con lo que yo te muestro, sino que te leerás la documentación del
Visual Basic e incluso habrás comprado algún que otro libro sobre
el tema este de la programación; en cualquier caso, debes saber que
un objeto, ya sea un módulo de clase ya sea un control, no se puede
copiar así por las buenas.
Para que lo
entiendas mejor: (espero)
Supongamos que tenemos una variable, por ejemplo la variable de tipo
string sNombre, que tiene como valor "el
Guille".
Sigamos suponiendo que queremos hacer una copia de dicha variable,
(realmente de su contenido), en otra variable, por ejemplo en sCopia.
Para realizar dicha copia, lo único que hay que hacer es: sCopia
= sNombre y a partir de ese momento, el contenido de sCopia
será el mismo que el de sNombre, (en este caso de suposiciones,
será "el Guille").
Si después cambiamos el contenido de la variable sNombre no
afectará al contenido de sCopia, ya que lo que se hizo fue copiar
el contenido de sNombre, es decir se creó una nueva cadena y se
guardó en la variable sCopia.
(Si yo fuera un experto en representaciones gráficas, te mostraría
un dibujito con las variables y sus contenidos, pero como soy un
desastre para esto de las "representaciones", sobre todo
si son gráficas, pues te lo imaginas o simplemente sigues leyendo,
que puede ser que hasta te enteres de lo que estoy hablando...)
Para probarlo, muestra el contenido de las dos variables, cambia el
contenido de sNombre y vuelve a mostrar, verás que cada una de las
variables tiene un valor distinto.
¿Cómo? Que
quieres ver el código completo... ¡Valeeee! ¡No insistas!, aquí
lo tienes:
Crea un nuevo proyecto e inserta este código en el evento Form_Load
Show ' Por si se te olvida ponerlo...
Dim sNombre As String
Dim sCopia As String
' Asignamos el contenido a sNombre y hacemos la copia
sNombre = "el Guille"
sCopia = sNombre
' Mostramos los contenidos
Print "El original: " & sNombre
Print "La copia: " & sCopia
' Cambiamos el contenido de sNombre
sNombre = "Guillermo"
' Volvemos a mostrar
Print
Print "El original: " & sNombre
Print "La copia: " & sCopia
Como podrás
comprobar, el original cambia, pero la copia permanece igual. Es
decir, el que se cambie el original no afecta a la copia, ya que son
dos "cosas" distintas.
Pero esto mismo no
se puede hacer con los objetos. Al menos no de la forma simple de
una asignación.
Para que sepas por dónde van los tiros, practiquemos con un
ejemplo.
Supongamos, (sigo
suponiendo, pero en estos casos, deberías "meterte" de
lleno en el tema y convertir estas suposiciones en código), que
queremos hacer una copia de un objeto del tipo cColega, (la
clase que hemos estado usando en las entregas anteriores y de la
cual más tarde te mostraré el código completo, ya que en las
entregas anteriores no lo hice, y sólo te mostré parte del código
y he recibido algunas quejas indicándome que faltaba código... mea
culpa!)
Pero para no caer en errores de suposiciones, (algunas veces supongo
que entiendes lo que digo y puede que "suponga" mal, así
que... dejémonos de suposiciones y vayamos a cosas concretas), te
voy a mostrar el código completo para que entiendas lo que quiero
explicarte... que con tanto suponer y tanta parrafada, no se si te
habrás perdido o seguirás en sintonía...
Declaramos una
variable para que contenga un objeto del tipo cColega y le asignamos
algún valor:
Dim tColega As
cColega ' La variable que contendrá un objeto del tipo cColega
Set tColega = New cColega ' Ahora está preparada para contener
datos
tColega.Nombre = "Guille" ' Asignamos los datos
tColega.email = "guille@costasol.net"
Ahora creamos otra
variable en la que queremos copiar lo que tiene el objeto tColega:
Dim CopiaColega
As cColega
Set CopiaColega = New cColega ' Creamos un nuevo objeto, aunque,
como después verás, no es necesario
Si hacemos esta
asignación: CopiaColega = tColega, recibiremos un error, ya
que Visual Basic espera que se estén copiando datos normales, en
este caso espera que tanto CopiaColega como tColega tengan
propiedades por defecto que se puedan copiar de la misma forma que
se copian dos variables normales (como vimos en el caso anterior de
sNombre y sCopia)
Cuando queremos "copiar" objetos, hay que usar SET, (no
comento más, ya que después lo aclaro), por tanto, lo que se
debería hacer es:
Set CopiaColega = tColega
Pero vamos a comprobar que no es oro todo lo que reluce.
Mostramos el contenido de CopiaColega
Text1.Text = "Contenido de CopiaColega: " & vbCrLf
& CopiaColega.Nombre & " " & CopiaColega.email
Ahora cambiamos el nombre de tColega
tColega.Nombre = "Guillermo"
Y volvemos a mostrar el contenido de CopiaColega
Text1.Text = Text1.Text & vbCrLf & _
"Contenido de CopiaColega después de
cambiar el nombre de tColega: " & vbCrLf & _
CopiaColega.Nombre & " " &
CopiaColega.email & vbCrLf
Para probar esto
que te digo y puedas ver y no tener que creértelo porque yo te lo
diga, en el formulario que tienes creado de la prueba anterior...
¿cómo? ¿que no has probado lo anterior? entonces, tendrás que
crear un nuevo proyecto... (si quieres, claro)
Añade un CommandButton (Command1) y una caja de texto (Text1) con
la propiedad MultiLine = True y ScrollBars = Both y pega el código,
(sí, lo que está en negrita, incluso la asignación que da el
error, para que compruebes que es verdad y que da un error, así vas
aprendiendo de los errores...)
Pulsa F5 y haz click en el botón, verás que es lo que ocurre.
Si todo va como debería ir, te habrá mostrado esto:
Contenido de
CopiaColega:
Guille guille@costasol.net
Contenido de CopiaColega después de cambiar el nombre de tColega:
Guillermo guille@costasol.net
O sea que no
teníamos una copia... entonces ¿que tenemos?
Pues, dos variables que "apuntan" al mismo objeto. Con las
consecuencias que esto tiene: que si se modifica el contenido de una
de las variables, el otro objeto también "aparenta" que
se ha modificado... y digo aparenta, porque en realidad sólo existe
un objeto del tipo cColega en la memoria, pero hay dos variables que
apuntan a ese objeto.
En otros lenguajes de programación sería algo así como un
puntero.
Como puedes
comprobar, me repito, (hace un par de entregas vimos algo de esto),
pero es para que te quede bien claro el concepto.
Entonces... ¿cómo
se puede hacer una copia de un objeto?
Pues manualmente, copiando cada una de las propiedades del objeto
original en la copia.
Para este caso si que es necesario declarar el objeto de destino
como NEW, ya que, en el caso anterior, no era necesario crear un
nuevo objeto cuando lo que "pretendíamos" era
"apuntar" al mismo objeto en memoria.
Pruébalo quitando la línea con este código: Set CopiaColega =
New cColega y verás que funciona igual (de mal)
La explicación es: que al ser una variable que simplemente hace
referencia a un objeto ya existente, no es necesario crear un nuevo
objeto que después no se va a usar.
Veamos el código
de la segunda prueba, haciendo copia de cada una de las propiedades.
Añade un nuevo botón e inserta este código, después pruébalo y
verás que el cambio del original no afecta a la copia, por la
sencilla razón de que son dos objetos totalmente diferentes.
Private Sub Command2_Click()
' Creamos una variable y le asignamos datos
Dim tColega As cColega ' La variable que contendrá un objeto del tipo cColega
Set tColega = New cColega ' Ahora está preparada para contener datos
tColega.Nombre = "Guille" ' Asignamos los datos
tColega.email = "guille@costasol.net"
'
' Creamos otra variable en la que queremos copiar
' lo que tiene el objeto tColega:
Dim CopiaColega As cColega
Set CopiaColega = New cColega
' Ahora copiamos cada una de las propiedades:
CopiaColega.Nombre = tColega.Nombre
CopiaColega.email = tColega.email
' Mostramos el contenido de CopiaColega
Text1.Text = "Contenido de CopiaColega: " & vbCrLf & CopiaColega.Nombre _
& " " & CopiaColega.email
' Ahora cambiamos el nombre de tColega
tColega.Nombre = "Guillermo"
' Y volvemos a mostrar el contenido de CopiaColega
Text1.Text = Text1.Text & vbCrLf & "Contenido de CopiaColega después de_
cambiar el nombre de tColega: " & vbCrLf & CopiaColega.Nombre _
& " " & CopiaColega.email & vbCrLf
' En este caso no se ha alterado el valor de CopiaColega... como era de esperar
End Sub
Pues esto mismo es
lo que tendríamos que hacer en un método que hiciese una copia del
objeto: copiar cada una de las propiedades de dicho objeto. Este
tipo de métodos suele llamarse Clone, (por lo de clonación
o copia idéntica), y se podría codificar de esta forma:
Public Function Clone() As cColega
' Esta función devolverá una copia "nueva" de éste mismo objeto
'
Dim nuevoColega As cColega ' Un objeto del tipo cColega
'
Set nuevoColega = New cColega ' Crear un nuevo objeto
'
' Asignar cada una de las propiedades de esta clase
With nuevoColega
.email = Me.email
.FechaNacimiento = Me.FechaNacimiento
.Nombre = Me.Nombre
End With
' Devolver el objeto "cloneado"
Set Clone = nuevoColega
End Function
Te explico un poco todo esto:
-
La función devuelve un objeto del mismo tipo
que la clase, ya que de lo que se trata es de hacer una copia
del objeto en sí.
-
Se crea una variable temporal del tipo a
devolver, (que es del mismo tipo que el objeto o clase), y se
asigna un NUEVO objeto a dicha variable.
-
Se asigna al nuevo objeto los valores del
objeto que implementa el método Clone, para ello se usa ME,
aunque sólo para mayor claridad, de ésta forma sabes que se
está refiriendo al propio objeto en el que se ha creado la
función.
-
Por último se devuelve una referencia al
nuevo objeto creado y con los datos copiados. El SET es
necesario por lo que antes te he comentado de que lo que se
quiere "copiar" es el objeto entero. En esta ocasión SET
Clone = nuevoColega devuelve una referencia al objeto nuevoColega
que no es ni más ni menos que el NUEVO objeto que acabamos de
crear.
Para usarlo,
simplemente asignaremos a la variable de destino lo que la función
(o método) Clone devuelva:
Set CopiaColega = tColega.Clone
que no es ni más ni menos que una "nueva" copia del
objeto tColega.
Como puedes comprobar en la función Clone lo único que hacemos es
"encapsular" lo que antes hicimos manualmente, es decir
"ocultamos" lo que la función hace para copiar el objeto,
ya que al usuario lo único que le interesa es saber que ése
método hace una nueva copia del objeto que lo implementa. Y si
añadimos nuevas propiedades a la clase, lo único que tendríamos
que hacer es añadir el código correspondiente para que las nuevas
propiedades también se copien al utilizar el método Clone.
Veamos el código
necesario para "probar" que todo esto que digo funciona.
Añade un nuevo botón al formulario y pega el siguiente código:
Private Sub Command3_Click()
' Creamos una variable y le asignamos datos
Dim tColega As cColega ' La variable contendrá un objeto del tipo cColega
Set tColega = New cColega ' Ahora está preparada para contener datos
tColega.Nombre = "Guille" ' Asignamos los datos
tColega.email = "guille@costasol.net"
'
' Creamos otra variable en la que queremos copiar
' lo que tiene el objeto tColega:
Dim CopiaColega As cColega
'
' No es necesario crear el nuevo objeto, ya que el método Clone
' devuelve un nuevo objeto
'Set CopiaColega = New cColega
'
' Hacemos una clonación
Set CopiaColega = tColega.Clone
'
' Mostramos el contenido de CopiaColega
Text1.Text = "Contenido de CopiaColega: " & vbCrLf & CopiaColega.Nombre _
& " " & CopiaColega.email
' Ahora cambiamos el nombre de tColega
tColega.Nombre = "Guillermo"
' Y volvemos a mostrar el contenido de CopiaColega
Text1.Text = Text1.Text & vbCrLf & "Contenido de CopiaColega después _
de cambiar el nombre de tColega: " & vbCrLf & CopiaColega.Nombre _
& " " & CopiaColega.email & vbCrLf
'
' Usando Clone tampoco se altera el objeto copiado
'
' Cambiemos el contenido del nombre de la copia
CopiaColega.Nombre = "Pepe"
' Mostramos el contenido de la propiedad Nombre de los dos objetos
Text1.Text = Text1.Text & vbCrLf & "Contenido de tColega.Nombre: " _
& tColega.Nombre
Text1.Text = Text1.Text & vbCrLf & "Contenido de CopiaColega.Nombre: " _
& CopiaColega.Nombre
End Sub
Ejecuta el programa
y pulsa en el botón que acabas de añadir, verás que te muestra
esto:
Contenido de
CopiaColega:
Guille guille@costasol.net
Contenido de CopiaColega después de cambiar el nombre de
tColega:
Guille guille@costasol.net
Contenido de tColega.Nombre: Guillermo
Contenido de CopiaColega.Nombre: Pepe
Es decir, que los
cambios que se hagan a cualquiera de las dos variables serán
independientes y no se "mezclarán", por la sencilla
razón de que cada una de las variables "apunta" a un
objeto diferente.
Otra forma de
clonar objetos
Existe otra forma de hacer clonaciones de objetos. Pero para ello
hay que tener el Visual Basic 6.0, ya que con las versiones
anteriores no funciona.
Te dejo el link a la página que tiene el código de ejemplo, (y la
página explicativa), para que sepas cómo hacerlo, por ahora no te
doy más explicaciones que las que pueda haber en los comentarios y
en dicha página, entre otras cosas porque se tratan temas que aún
no se han explicado, así que... eso es lo que hay, pero al menos
hay algo, que en definitiva es lo importante ¿verdad?
Link
a la página de clonación de objetos usando Visual Basic 6.0
Y hasta aquí hemos
llegado.
En la próxima entrega, posiblemente, veremos cómo crear
nuestras propias colecciones... espero que en esa ocasión sea
así... si es que antes no se me ocurre alguna cosilla nueva... ¡ya
veremos!
Nos vemos
P.S.
Aquí el código completo de la
clase y el proyecto de prueba: basico39_cod.zip 3.93 KB

|