Mas Sobre Constructores
En el post anterior hablamos sobre el método especial "
_new", que nos ayuda a dar valores a los parámetros o realizar instrucciones justo cuando instanciamos un objeto.
Los métodos también admiten (al igual que las funciones y las subrutinas),
parámetros opcionales (optional). Además tenemos funciones en gambas que permiten conocer que tipo de parámetro es el que se le esta pasando al instanciar la clase.
Con esta dos herramientas, podemos programar que un mismo método _new, pueda crear objetos usando diversos tipos y números de parámetros.
Por ejemplo:
Tenemos la clase ClassCirculo, con la cual se crean Circulos.
Podemos definir los circulos de diversas maneras:
- Forma 1: x, y, radio, nos dan la X e Y y radio (integer)
- Forma 2: x, y, radio, nos dan la X e Y y radio (pero son Float)
- Forma 3: classe Coordenada, radio (circulo dado el centro por la clase coordenada y su radio)
- Forma 4: clase coordenda1,coordenado2,coordenada3 (circulo que pase por 3 puntos)
¿como se programa?
Lo que tenemos que hacer es usar varias ordenes If... then,,, para que segun sea el tipo de parametro pasar crearlo.
Para saber el tipo de parámetro, usamos:
- La orden TypeOf(parametro1), nos devuelve un número que se identifica con el tipo de variable (ver http://www.gambasdoc.org/help/lang/typeof?v3 )
- Si sabemos que es un objeto Object.Type(parametro1), que nos dá el nombre de la clase.
¿Como se defineria la clase ClassCirculo?
-->
Public
Sub
_new(Optional
parametro1 As
Variant,
Optional
parametro2 As
Variant,
Optional
parametro3 As
Variant)
'
Forma: x, y, radio : nos dan la X e Y y radio (integer)
If
TypeOf(parametro1) =
gb.Integer
And
TypeOf(parametro2) =
gb.Integer
And
TypeOf(parametro3) =
gb.integer
Then
Print
"Me
pasan 3 numeros integer, en la forma X, Y, Radio"
'realizo
copia de propiedades...
'...
hx =
parametro1
hy =
parametro2
hradio =
parametro3
estado =
"iniciado"
Return
Else
'
Forma: x, y, radio : nos dan la X e Y y radio (pero son Float)
If
TypeOf(parametro1) =
gb.float
And
TypeOf(parametro2) =
gb.float
And
TypeOf(parametro3) =
gb.float
Then
Print
"Me
pasan 3 numeros float, en la forma X, Y, Radio"
'crearia
el circulo
'...
hx =
parametro1
hy =
parametro2
hradio =
parametro3
Return
Else
'
forma: classe Coordenada, radio (circulo dado el centro por la clase
coordenada y su radio)
If
Object.Type(parametro1)
=
"ClassCoordenada"
And
TypeOf(parametro2) =
gb.float
Then
Print
"Me
pasan una clase ClassCoordenada, y el Radio (float)"
'crearia
el circulo con los datos pasado
'....
'
Return
Else
'
Forma: clase coordenda1,coordenado2,coordenada3 (circulo que pase por
3 puntos)
If
Object.Type(parametro1)
=
"ClassCoordenada"
And
Object.Type(parametro2)
=
"ClassCoordenada"
And
Object.Type(parametro3)
=
"ClassCoordenada"
Then
Print
"Me
pasan 3 clases ClassCoordenada"
'se
crearia el circulo teniendo en cuenta 3 coordenadas.
'....
'
Return
Endif
Endif
Endif
Endif
¿como usar la clase?
-->
Print
"================================================================"
Print
"=
Constructores ="
Print
"================================================================"
'
Forma: x, y, radio : nos dan la X e Y y radio (integer)
Print
"Constructor
caso:"
c1 =
New
ClassCirculo(2,
3,
4)
'
Forma: x, y, radio : nos dan la X e Y y radio ( Float)
Print
"Constructor
caso:"
c2 =
New
ClassCirculo(2.3,
24.2,
34.2)
'
forma: classe Coordenada, radio (circulo dado el centro por la clase
coordenada y su radio (float))
Print
"Constructor
caso:"
c3 =
New
ClassCirculo(coord1, 34.3)
'
Forma: clase coordenda1,coordenado2,coordenada3 (circulo que pase por
3 puntos)
Print
"Constructor
caso:"
c4 =
New
ClassCirculo(coord1, coord2, coord3)
Hacer una Copia de un Objeto:
Para copiar variables en Gambas, usamos el operador igual "=".
Por ejemplo
-->
dim
Nombre as
string
dim
NombreCopia as
string
Nombre=”Julio”
NombreCopia=nombre
print
Nombre, NombreCopia
Sin embargo, con objetos no podemos hacer lo mismo, ya que el operador igual ("=") lo que hace es copiar la referencia del objeto (no hace copia).
Cualquier cambio que haríamos en el objecto copiado modificaria al objeto original.
-->
Print
"Coordenadas
Mal copiadas por referencia!!!: "
Print
coord1.escribe()
Print
coord2.escribe()
coord2.y
=
234343455
Print
"Coordenadas:
"
Print
coord1.escribe()
Print
coord2.escribe()
Obtenemos en pantalla...
Coordenadas Mal copiadas por referencia!!!:
X: 23 Y: 34
X: 23 Y: 34
Coordenadas:
X: 23 Y: 234343455
X: 23 Y: 234343455
Como ves, al alterar la clase copiada (coord2), se modifica tambien la clase origen (coord1)
Para copiar objetos, tenemos que hacerlo mediante lineas de código, que se encarguen de copiar y asignar las propieades (sus valores) del objeto Origen a las otras propiedades del objeto_copia. Por ejemplo, con este método dentro de la clase ClassCoordenada
-->
Public
Function
copia(origen As
ClassCoordenada) As
ClassCoordenada
Me.x
=
origen.x
Me.y
=
origen.y
End
'Esta
es la opcion más correcta vease comentarios...
Public
Sub
copia(origen As
ClassCoordenada)
Me.x
=
origen.x
Me.y
=
origen.y
End
Para usarlo:
-->
coord1 =
New
ClassCoordenada
coord2 =
New
ClassCoordenada
coord1.x
=
23
coord1.y
=
34
coord2.copia(coord1)
Print
"Coordenadas:
Copia mediante metodo "
Print
coord1.escribe()
Print
coord2.escribe()
coord2.y
=
3433445
Print
"Coordenadas
Cambio: "
Print
coord1.escribe()
Print
coord2.escribe()
Y es resultado...
Coordenadas: Copia mediante metodo
X: 23 Y: 34
X: 23 Y: 34
Coordenadas Cambio:
X: 23 Y: 34
X: 23 Y: 3433445
Como veis, ahora si, se copia bien, ya que al modificar la clase copiada, la de origen no se modifica.
Para terminar, tambien podemos usar el método contructor para que crear una copia de un objeto:
-->
Public
Sub
_new(Optional
parametro1 As
Variant,
Optional
parametro2 As
Variant,
Optional
parametro3 As
Variant)
Dim
clase As
String
If
TypeOf(parametro1) =
gb.Object
And
If
Object.Type(parametro1)
=
"ClassCirculo"
Then
hy =
parametro1.y
hx =
parametro1.x
hradio =
parametro1.radio
estado =
parametro1.leerEstado()
Return
Endif
…..
…..
Y usarlo asi:
-->
Print
"Proceso
de copia de circulo.."
copia
=
New
ClassCirculo(c1)
Para más información:
http://www.gambas-es.org/viewtopic.php?f=1&t=100&highlight=objetos
Descarga del Código Fuente de ejmplo. tanto de Sobre Constructores y Copia de Objetos :
Enlace
Nota: Actualizacion 3/8/2013 (new)
Tras estudiar un ejemplo del foro de gambas de Francia (
http://www.gambasforge.org/code-62-copier-un-controle-ou-un-conteneur-et-ses-enfants.html), sobre como clonar controels, he realizado algunos cambios para que nos sirva para objetos complejos (con propiedades que sean arrays, clases, variant, ...)
Os dejo aqui la función que lo hace:
Public
Sub
CopyObject(hObjeto As
Object)
As
Object
Dim
hNewMe As
Object
=
Object.New(Object.Type(hObjeto))
'se genera
un objeto de la mismo tipo que nos pasan
Dim
s As
String
'variable
utilizada para almacenar el valor de hclass.symbols
Dim
hclass As
Class
=
Object.Class(hObjeto)
'contiene
el valor de la clase del objeto
Dim
hChild As
Object
Dim
nuevoObjeto As
Object
Dim
caso As
Integer
'tipo de
dato de la propiedad del objeto
Dim
contador, a As
Integer
'para
usarlo en bucle si son arrays
Dim
arrayPosible As
Object
'Inicio
de la copia de las propiedades....
For
Each
s In hclass.Symbols
If
s =
"Chlidren"
Then
Continue
If
Not
hclass[s].ReadOnly
Then
caso =
TypeOf(Object.GetProperty(hObjeto,
s))
Select
Case
caso
Case
gb.Object
'la
propiedad es un objeto, vuelvo a llamar a la funcion para que me
extraiga los valores y no las referencias
nuevoObjeto =
CopyObject(Object.GetProperty(hObjeto,
s))
Object.SetProperty(hNewMe,
s, nuevoObjeto)
Try
contador =
Object.GetProperty(hObjeto,
s).count
If
Error
Then
'no
es un array
Else
For
a =
0
To
contador -
1
nuevoObjeto.add(Object.GetProperty(hObjeto,
s)[a])
Next
Endif
Default
'la
propiedad no es un objeto, copio el valor
Object.SetProperty(hNewMe,
s, Object.GetProperty(hObjeto,
s))
End
Select
Endif
Next
'devuelvo
la copia del objeto
Return
hNewMe
End
Y un ejemplo:
http://jsbsan.blogspot.com.es/2013/08/poo-en-gambas3-copiar-objetos.html
Nota 2:
Esta función copia tanto las propiedades como los métodos que tenga el objeto.
No copia variables publicas definidas dentro del objeto (ni por supuesto las privadas)