Beruflich Dokumente
Kultur Dokumente
CARACTERSTICAS DE .NET
Introduccin
En esta primera leccin veremos los tipos de datos que .NET Framework pone a nuestra
disposicin, as mismo veremos las diferencias con respecto a los tipos de datos de Visual
Basic 6.0 y las equivalencias entre los tipos de ambos entornos, de esta forma nos resultar
ms fcil familiarizarnos. Aunque no debemos olvidar que en .NET los tipos de datos tienen un
tratamiento, en algunos casos, especial que pueden llevarnos a confusin, por tanto en los
casos que pueda existir esa posibilidad de funcionamiento diferente, veremos ejemplos de
cmo los manejbamos en VB6 y cmo tendremos que usarlos desde Visual Basic 2005.
A continuacin daremos un repaso a conceptos bsicos o elementales sobre los tipos de
datos, que si bien nos sern familiares, es importante que lo veamos para poder comprender
mejor cmo estn definidos y organizados los tipos de datos en .NET y de paso veremos las
equivalencias con respecto a Visual Basic 6.0.
En los siguientes enlaces tenemos los temas a tratar en esta primera leccin del mdulo sobre
las caractersticas del lenguaje Visual Basic 2005
Tipos primitivos
Veamos en la siguiente tabla los tipos de datos definidos en .NET Framework y los alias
utilizados en Visual Basic 2005, as como el equivalente de VB6.
.NET Framework
VB 2005
VB6
System.Boolean
Boolean
Boolean *
System.Byte
Byte
Byte
System.Int16
Short
Integer
System.Int32
Integer
Long
System.Int64
Long
N.A.
System.Single
Single
Single
System.Double
Double
Double
System.Decimal
Decimal
Currency *
System.Char
Char
N.A. (ChrW)
System.String
String
String *
System.Object
Object
Variant / Object *
System.DateTime
Date
Date *
System.SByte
SByte
N.A.
System.UInt16
UShort
N.A.
System.UInt32
UInteger
N.A.
System.UInt64
ULong
N.A.
Los tipos mostrados en la tabla 1 son los tipos primitivos de .NET y por extensin de Visual
Basic 2005, es decir son tipos "elementales" para los cuales cada lenguaje define su propia
palabra clave equivalente con el tipo definido en el CTS de .NET Framework. Todos estos tipos
primitivos podemos usarlos tanto por medio de los tipos propios de Visual Basic, los tipos
definidos en .NET o bien como literales. Por ejemplo, podemos definir un nmero entero literal
indicndolo con el sufijo I: 12345I o bien asignndolo a un valor de tipo Integer o a un tipo
Sytem.Int32 de .NET. La nica excepcin de los tipos mostrados en la tabla 1 es el tipo de
datos Object, este es un caso especial del que nos ocuparemos en la prxima leccin.
Tipo de datos
Short
Smbolo
N.A.
Carcter
S
Integer
Long
&
Single
Double
Decimal
UShort
N.A.
US
UInteger
N.A.
UI
ULong
N.A.
UL
Los tipos por valor son tipos de datos cuyo valor se almacena en la pila o en la memoria
"cercana", como los numricos que hemos visto. Podemos decir que el acceso al valor
contenido en uno de estos tipos es directo, es decir se almacena directamente en la memoria
reservada para ese tipo y cualquier cambio que hagamos lo haremos directamente sobre
dicho valor, de igual forma cuando copiamos valores de un tipo por valor a otro, estaremos
haciendo copias independientes.
Por otro lado, los tipos por referencia se almacenan en el "monto" (heap) o memoria "lejana",
a diferencia de los tipos por valor, los tipos por referencia lo nico que almacenan es una
referencia (o puntero) al valor asignado. Si hacemos copias de tipos por referencia, realmente
lo que copiamos es la referencia propiamente dicha, pero no el contenido.
Estos dos casos los veremos en breve con ms detalle.
Variables y constantes
Disponer de todos estos tipos de datos no tendra ningn sentido si no los pudiramos usar de
alguna otra forma que de forma literal. Y aqu es donde entran en juego las variables y
constantes, no vamos a contarte qu son y para que sirven, salvo en el caso de las
constantes, ya que no todos los desarrolladores las utilizamos de la forma adecuada.
Declarar variables
La declaracin de las variables en Visual Basic 2005 se hace de la misma forma que en VB6, o
casi, las excepciones vienen dadas, como hemos comentado antes, de la posibilidad de
obligar a definir el tipo de cada variable y de cmo podemos definir ms de una variable en
una misma instruccin Dim.
Para no embrollar mucho la cosa, veamos ejemplos de cmo definir o declarar variables
siguiendo las buenas costumbres, es decir, indicando siempre el tipo de datos de la variable.
En VB6 podamos definir ms de una variable en una misma instruccin Dim, aunque
dependiendo de cmo hiciramos esa declaracin poda ser que, normalmente para nuestro
pesar, que no todas las variables fuesen del tipo que "supuestamente" habamos querido
indicar.
Por ejemplo, con esta declaracin:
Dim a, b, c As Integer
A primera vista estamos declarando tres variables de tipo Integer, pero realmente solo
declara con el tipo indicado a la ltima variable, las otras dos, se declaran con tipo Variant o
el tipo de datos predefinido.
En Visual Basic 2005 al usar esa misma lnea de cdigo estamos declarando tres variables de
tipo Integer, esto es algo que debemos tener en cuenta, sobre todo si nuestra intencin era
hacer precisamente lo que VB6 haca, es decir, declarar dos variables de tipo Variant y una de
tipo Integer.
En esa misma lnea podemos declarar y asignar ms variables, pero todas deben estar
indicadas con el tipo de datos:
Dim a As Integer = 10, b As Integer = 25
Por supuesto, el tipo de datos puede ser cualquiera de los tipos primitivos:
Dim a As Integer = 10, b As Integer = 25, s As String = "Hola"
Aunque para que el cdigo sea ms legible, y fcil de depurar, no deberamos mezclar en una
misma instruccin Dim ms de un tipo de datos.
Nota:
Es importante saber que en las cadenas de Visual Basic 2005 el valor de una
variable de tipo String no inicializada NO es una cadena vaca como ocurra en
VB6, sino un valor nulo (Nothing).
Si bien en VB6 no existe el tipo de datos Char, si podemos convertir un valor numrico en un
carcter (realmente en una cadena) o bien podemos convertir un carcter en su
correspondiente valor numrico.
Dim c As String
c = Chr(65)
Dim n As Integer
n = Asc("A")
En Visual Basic 2005 tambin podemos usar esas mismas funciones, aunque en el caso de
Chr, el valor que devuelve esta funcin es un valor de tipo Char, no de tipo String como
ocurre en VB6, pero debido a que un valor de tipo Char se puede convertir en una cadena,
podemos hacer una asignacin como la mostrada en el cdigo anterior sin ningn tipo de
problemas.
Si nuestra intencin es asignar un valor Char a una variable, adems de la funcin Chr,
podemos hacerlo con un literal, ese valor literal estar encerrado entre comillas dobles, (al
igual que una cadena), aunque para que realmente sea un carcter debemos agregarle una c
justo despus del cierre de las comillas dobles:
Dim c As Char = "A"c
Nota:
Aunque en esta captura muestre: C:\vbexpB1 en Default project location,
salvo que lo cambiemos, aparecer el path por defecto dentro de Mis
documentos.
Como podemos observar, aparecen pocas opciones, realmente el IDE de Visual Basic 2005
Express nos muestra las predeterminadas para los desarrolladores de Visual Basic, si bien,
podemos hacer que se muestren todas las disponibles, para hacerlo, debemos marcar la
casilla que est en la parte inferior izquierda en la que podemos leer: Mostrar todas las
configuraciones, al seleccionar esa opcin nos mostrar un nmero mayor de opciones, tal
como podemos ver en la figura 1.3:
10
Figura 1.4. Aviso de Option Strict al declarar una variable sin tipo
Nota:
Una de las ventajas del IDE (Integrated Development Environment, entorno de
desarrollo integrado) de Visual Basic 2005 es que nos avisa al momento de
cualquier fallo que cometamos al escribir el cdigo, este "pequeo" detalle,
aunque alguna veces puede llegar a parecer fastidioso, nos facilita la escritura
de cdigo, ya que no tenemos que esperar a realizar la compilacin para que
tengamos constancia de esos fallos.
11
12
Visual Basic siempre hemos querido tener: Que nos avise cuando una variable la hemos
declarado pero no la utilizamos (Variable local no utilizada). Al tener marcada esta opcin
(normalmente como una Advertencia), si hemos declarado una variable y no la usamos en el
cdigo, (siempre que no le hayamos asignado un valor al declararla), nos avisar, tal como
podemos ver en la figura 1.6:
Rojo
Verde
Azul
End Enum
En este primer caso, el tipo de datos de cada miembro de la enumeracin ser Integer.
13
Rojo
Verde
Azul
End Enum
En este segundo caso, el valor mximo que podemos asignar a los miembros de una
enumeracin ser el que pueda contener un tipo de datos Long.
3- Indicando el atributo FlagsAttibute, (realmente no hace falta indicar el sufijo Attribute
cuando usamos los atributos) de esta forma podremos usar los valores de la enumeracin
para indicar valores que se pueden "sumar" o complementar entre s, pero sin perder el
nombre, en breve veremos qu significa esto de "no perder el nombre".
<Flags()> _
Rojo = 1
Verde = 2
Azul = 4
End Enum
Nota:
Los atributos los veremos con ms detalle en otra leccin de este mismo
mdulo.
14
Es decir, podemos "sumar" los valores definidos en la enumeracin. Antes de explicar con
detalle que beneficios nos puede traer el uso de este atributo, veamos una caracterstica de
las enumeraciones que no tenamos en VB6.
Como hemos comentado, las enumeraciones son constantes con nombres, pero en Visual
Basic 2005 esta definicin llega ms lejos que en VB6, de hecho, podemos saber "el nombre"
de un valor de una enumeracin, para ello tendremos que usar el mtodo ToString, (el cual se
usa para convertir en una cadena cualquier valor numrico).
Por ejemplo, si tenemos la siguiente asignacin:
Dim s As String = Colores.Azul.ToString
Rojo = 1
Verde = 2
Azul = 4
End Enum
15
Rojo = 1
Verde = 2
Azul = 4
End Enum
El contenido de la variable s ser: "Rojo, Azul", es decir, se asignan los nombres de los
miembros de la enumeracin que intervienen en ese valor, no el valor "interno".
Por tanto, podemos pensar que al igual que ocurra en VB6, podemos usar cualquier valor
para asignar a una variable declarada como una enumeracin, al menos si ese valor est
dentro del rango adecuado.
Pero en Visual Basic 2005 esto no es posible, al menos si lo hacemos de forma "directa" y con
Option Strict conectado, ya que recibiremos un error indicndonos que no podemos
convertir, por ejemplo, un valor entero en un valor del tipo de la enumeracin. En la figura 1.8
podemos ver ese error al intentar asignar el valor 3 a una variable del tipo Colores (definida
con el tipo predeterminado Integer).
16
Figura 1.8. Error al asignar un valor "normal" a una variable del tipo Colores
El error nos indica que no podemos realizar esa asignacin, pero el entorno integrado de
Visual Basic Express 2005 tambin nos ofrece alternativas para que ese error no se produzca,
esa ayuda se obtiene pulsando en el signo de admiracin que tenemos justo donde est el
cursor del ratn, pero no solo nos dice cmo corregirlo, sino que tambin nos da la posibilidad
de que el propio IDE se encargue de corregirlo, tal como podemos apreciar en la figura 1.9.
CType es una de las formas que nos ofrece Visual Basic 2005 de hacer conversiones entre
diferentes tipos de datos, en este caso convertimos un valor entero en uno del tipo Colores.
Si compilamos y ejecutamos la aplicacin, sta funcionar correctamente.
Aunque sabemos que es posible que usando CType no asignemos un valor dentro del rango
permitido. En este caso, el valor 3 podramos darlo por bueno, ya que es la suma de 1 y 2
(Rojo y Verde), pero que pasara si el valor asignado es, por ejemplo, 15? En teora no
deberamos permitirlo.
Estas validaciones podemos hacerlas de dos formas:
1- Con la clsica solucin de comprobar el valor indicado con todos los valores posibles.
2- Usando funciones especficas del tipo Enum. Aunque en este ltimo caso, solo podremos
comprobar los valores definidos en la enumeracin.
En el siguiente ejemplo podemos hacer esa comprobacin.
Sub mostrarColor(ByVal c As Colores)
17
c = Colores.Azul
End If
End Sub
Este cdigo lo que hace es comprobar si el tipo de datos Colores tiene definido el valor
contenido en la variable c, en caso de que no sea as, usamos un valor predeterminado.
Nota:
La funcin IsDefined slo comprueba los valores que se han definido en la
enumeracin, no las posibles combinaciones que podemos conseguir sumando
cada uno de sus miembros, incluso aunque hayamos usado el atributo
FlagsAttribute.
Rojo
18
Verde
Azul
End Enum
En este primer caso, el tipo de datos de cada miembro de la enumeracin ser Integer.
2- Indicando el tipo de datos que realmente tendr:
Enum Colores As Long
Rojo
Verde
Azul
End Enum
En este segundo caso, el valor mximo que podemos asignar a los miembros de una
enumeracin ser el que pueda contener un tipo de datos Long.
3- Indicando el atributo FlagsAttibute, (realmente no hace falta indicar el sufijo Attribute
cuando usamos los atributos) de esta forma podremos usar los valores de la enumeracin
para indicar valores que se pueden "sumar" o complementar entre s, pero sin perder el
nombre, en breve veremos qu significa esto de "no perder el nombre".
<Flags()> _
Rojo = 1
Verde = 2
Azul = 4
End Enum
Nota:
Los atributos los veremos con ms detalle en otra leccin de este mismo
mdulo.
19
Es decir, podemos "sumar" los valores definidos en la enumeracin. Antes de explicar con
detalle que beneficios nos puede traer el uso de este atributo, veamos una caracterstica de
las enumeraciones que no tenamos en VB6.
Como hemos comentado, las enumeraciones son constantes con nombres, pero en Visual
Basic 2005 esta definicin llega ms lejos que en VB6, de hecho, podemos saber "el nombre"
de un valor de una enumeracin, para ello tendremos que usar el mtodo ToString, (el cual se
usa para convertir en una cadena cualquier valor numrico).
Por ejemplo, si tenemos la siguiente asignacin:
Dim s As String = Colores.Azul.ToString
Rojo = 1
Verde = 2
Azul = 4
End Enum
20
Rojo = 1
Verde = 2
Azul = 4
End Enum
El contenido de la variable s ser: "Rojo, Azul", es decir, se asignan los nombres de los
miembros de la enumeracin que intervienen en ese valor, no el valor "interno".
21
Por tanto, podemos pensar que al igual que ocurra en VB6, podemos usar cualquier valor
para asignar a una variable declarada como una enumeracin, al menos si ese valor est
dentro del rango adecuado.
Pero en Visual Basic 2005 esto no es posible, al menos si lo hacemos de forma "directa" y con
Option Strict conectado, ya que recibiremos un error indicndonos que no podemos
convertir, por ejemplo, un valor entero en un valor del tipo de la enumeracin. En la figura 1.8
podemos ver ese error al intentar asignar el valor 3 a una variable del tipo Colores (definida
con el tipo predeterminado Integer).
Figura 1.8. Error al asignar un valor "normal" a una variable del tipo Colores
El error nos indica que no podemos realizar esa asignacin, pero el entorno integrado de
Visual Basic Express 2005 tambin nos ofrece alternativas para que ese error no se produzca,
esa ayuda se obtiene pulsando en el signo de admiracin que tenemos justo donde est el
cursor del ratn, pero no solo nos dice cmo corregirlo, sino que tambin nos da la posibilidad
de que el propio IDE se encargue de corregirlo, tal como podemos apreciar en la figura 1.9.
CType es una de las formas que nos ofrece Visual Basic 2005 de hacer conversiones entre
diferentes tipos de datos, en este caso convertimos un valor entero en uno del tipo Colores.
Si compilamos y ejecutamos la aplicacin, sta funcionar correctamente.
Aunque sabemos que es posible que usando CType no asignemos un valor dentro del rango
permitido. En este caso, el valor 3 podramos darlo por bueno, ya que es la suma de 1 y 2
(Rojo y Verde), pero que pasara si el valor asignado es, por ejemplo, 15? En teora no
deberamos permitirlo.
22
c = Colores.Azul
End If
End Sub
Este cdigo lo que hace es comprobar si el tipo de datos Colores tiene definido el valor
contenido en la variable c, en caso de que no sea as, usamos un valor predeterminado.
Nota:
La funcin IsDefined slo comprueba los valores que se han definido en la
enumeracin, no las posibles combinaciones que podemos conseguir sumando
cada uno de sus miembros, incluso aunque hayamos usado el atributo
FlagsAttribute.
Arrays (matrices)
Los arrays (o matrices) tambin es algo que podamos usar en VB6, si bien la forma en que se
almacena en la memoria y la forma en que podemos usarlas en Visual Basic 2005 ha
cambiado, aunque la forma en que podemos usarlas es idntica a VB6... o casi.
En Visual Basic 2005 la declaracin de un array la haremos de la misma forma que en VB6, en
el siguiente ejemplo declaramos un array de tipo String llamado nombres:
Dim nombres() As String
Al igual que en VB6, podemos indicar el nmero de elementos que contendr el array:
Dim nombres(10) As String
23
Tal como ocurre en VB6, al realizar esta declaracin lo que conseguimos es definir un array de
11 elementos: desde cero hasta 10. Si bien, en VB6 tenemos la posibilidad de indicar cual era
el valor del ndice inferior predeterminado de los arrays, podemos elegir entre cero y uno
mediante la instruccin Option Base indicando a continuacin un 0 o un 1. En Visual Basic
2005 no existe esa instruccin, es ms en Visual Basic 2005 todos los arrays deben tener
como ndice inferior el valor cero.
Otra posibilidad que tenamos en VB6 era indicar el rango de ndices que podamos asignar,
esto lo logrbamos usando la clusula To al definir un array, por ejemplo:
Dim nombres(10 To 25) As String
Pero esta declaracin es ilegal en Visual Basic 2005, por el hecho de que los arrays de .NET
siempre deben tener el valor cero como ndice inferior.
Lo que si podemos hacer en Visual Basic 2005 es usar To para indicar el valor mximo del
ndice, aunque no tiene la misma "potencia" que en VB6, al menos de esta forma el cdigo
resultar ms legible:
Dim nombres(0 To 10) As String
Con el cdigo anterior estamos creando un array de tipo String con tres valores cuyos ndices
van de cero a dos.
Si el array es bidimensional (o con ms dimensiones), tambin podemos inicializarlos al
declararlo, pero en este caso debemos usar doble juego de llaves:
Dim nombres(,) As String = {{"Juan", "Pepe"}, {"Ana", "Eva"}}
Juan
Pepe
Ana
Eva
24
Lo que tambin podemos hacer en Visual Basic 2005 es cambiar el tamao de un array y
mantener los valores que tuviera anteriormente, para lograrlo debemos usar ReDim Preserve.
Si bien tanto ReDim como ReDim Preserve se pueden usar en arrays de cualquier nmero de
dimensiones, en los arrays de ms de una dimensin solamente podemos cambiar el tamao
de la ltima dimensin.
otros = nombres
nombres(0) = "Antonio"
25
Que debido a que los arrays son tipos por referencia, solamente existe una copia de los datos
y tanto la variable nombres como la variable otros lo que contienen es una referencia (o
puntero) a los datos.
Si realmente queremos tener copias independientes, debemos hacer una copia del array
nombres en el array otros, esto es fcil de hacer si usamos el mtodo CopyTo. ste mtodo
existe en todos los arrays y nos permite copiar un array en otro empezando por el ndice que
indiquemos.
El nico requisito es que el array de destino debe estar inicializado y tener espacio suficiente
para contener los elementos que queremos copiar.
En el siguiente cdigo de ejemplo hacemos una copia del contenido del array nombres en el
array otros, de esta forma, el cambio realizado en el elemento cero de nombres no afecta al
del array otros.
Dim nombres() As String = {"Juan", "Pepe", "Ana", "Eva"}
ReDim otros(nombres.Length)
nombres.CopyTo(otros, 0)
nombres(0) = "Antonio"
Adems del mtodo CopyTo, los arrays tienen otros miembros que nos pueden ser de utilidad,
como por ejemplo la propiedad Length usada en el ejemplo para saber cuantos elementos
tiene el array nombres.
Para averiguar el nmero de elementos de un array, tambin podemos usar la funcin
UBound, que es la que nos serva en Visual Basic 6.0 para saber esa informacin.
Sin embargo, el uso de la funcin LBound, (que sirve para averiguar el ndice inferior de un
array), no tiene ningn sentido en Visual Basic 2005, ya que todos los arrays siempre tienen
un valor cero como ndice inferior.
Para finalizar este tema, solo nos queda por decir, que los arrays de Visual Basic 2005
realmente son tipos de datos derivados de la clase Array y por tanto disponen de todos los
miembros definidos en esa clase, aunque de esto hablaremos en la prxima leccin, en la que
tambin tendremos la oportunidad de profundizar un poco ms en los tipos por referencia y
en como podemos definir nuestros propios tipos de datos, tanto por referencia como por
valor.
26
Clases y estructuras
Introduccin
En la leccin anterior vimos los tipos de datos predefinidos en .NET Framework, en esta
leccin veremos cmo podemos crear nuestros propios tipos de datos, tanto por valor como
por referencia.
Tambin tendremos ocasin de ver los distintos niveles de accesibilidad que podemos aplicar a
los tipos, as como a los distintos miembros de esos tipos de datos. De los distintos miembros
que podemos definir en nuestros tipos, nos centraremos en las propiedades para ver en
detalle los cambios que han sufrido con respecto a VB6. Tambin veremos temas relacionados
con la programacin orientada a objetos (POO) en general y de forma particular los que
ataen a las interfaces.
27
agregar mltiple funcionalidad a nuestra nueva clase. Esta funcionalidad nos servir para
aprovechar la funcionalidad de muchas de las clases existentes en .NET Framework,
funcionalidad que solamente podremos aplicar si previamente hemos firmado un contrato que
asegure a la clase de .NET que la nuestra est preparada para soportar esa funcionalidad,
esto lo veremos dentro de poco con ms detalle.
Nota:
Todos los tipos de datos de .NET, ya sean por valor o por referencia siempre
estn derivados de la clase Object, por tanto podremos llamar a cualquiera de
los mtodos que estn definidos en esa clase.
Aunque en el caso de los tipos de datos por valor, cuando queremos acceder a la
clase Object que contienen, .NET Framework primero debe convertirla en un
28
Nota:
En Visual Basic 2005 cualquier cdigo que queramos escribir estar dentro de
una clase.
En Visual Basic 2005 las clases se definen usando la palabra clave Class seguida del nombre
de la clase, esa definicin acaba indicndolo con End Class.
En el siguiente ejemplo definimos una clase llamada Cliente que tiene dos campos pblicos.
Class Cliente
End Class
Una vez definida la clase podemos agregar los elementos (o miembros) que creamos
conveniente.
En el ejemplo anterior, para simplificar, hemos agregado dos campos pblicos, aunque
tambin podramos haber definido cualquiera de los miembros permitidos en las clases.
29
De todos estos conceptos nos ocuparemos en las siguientes lecciones, pero es necesario
explicar que existe este tipo de clase ya que ser el tipo de datos que el IDE de Visual Basic
2005 usar al crear aplicaciones del tipo consola, ya que ese ser el tipo de proyecto que
crearemos para practicar con el cdigo mostrado en este primer mdulo.
Enumeraciones
Campos
Propiedades
Eventos
Las enumeraciones, como vimos en la leccin anterior, podemos usarlas para definir valores
constantes relacionados, por ejemplo para indicar los valores posibles de cualquier
"caracterstica" de la clase.
Los campos son variables usadas para mantener los datos que la clase manipular.
Los mtodos son las acciones que la clase puede realizar, normalmente esas acciones sern
sobre los datos que contiene. Dependiendo de que el mtodo devuelva o no un valor,
podemos usar mtodos de tipo Function o de tipo Sub respectivamente.
Las propiedades son las "caractersticas" de las clases y la forma de acceder "pblicamente"
a los datos que contiene. Por ejemplo, podemos considerar que el nombre y los apellidos de
un cliente son dos caractersticas del cliente.
Los eventos son mensajes que la clase puede enviar para informar que algo est ocurriendo
en la clase.
30
mbito
Es el alcance que la definicin de un miembro o tipo puede tener. Es decir, cmo podemos
acceder a ese elemento y desde dnde podemos accederlo.
El mbito de un elemento de cdigo est restringido por el "sitio" en el que lo hemos
declarado. Estos sitios pueden ser:
Accesibilidad
A los distintos elementos de nuestro cdigo (ya sean clases o miembros de las clases)
podemos darle diferentes tipos de accesibilidad. Estos tipos de "acceso" dependern del
mbito que queramos que tengan, es decir, desde dnde podremos accederlos.
Los modificadores de accesibilidad son:
Por ejemplo, podemos declarar miembros privados a una clase, en ese caso, dichos miembros
solamente los podremos acceder desde la propia clase, pero no desde fuera de ella.
Nota:
Al igual que ocurre en VB6, al declarar una variable con Dim, por regla general,
el mbito que le estamos aplicando es privado, pero como veremos, en Visual
Basic 2005, dependiendo del tipo en el que declaremos esa variable, el mbito
puede ser diferente a privado.
Miembros compartidos
Por otro lado, los miembros compartidos de una clase o tipo, son elementos que no
pertenecen a una instancia o copia en memoria particular, sino que pertenecen al propio tipo
y por tanto siempre estn accesibles o disponibles, dentro del nivel del mbito y accesibilidad
que les hayamos aplicado, y su tiempo de vida es el mismo que el de la aplicacin.
31
Nota:
Lo ms parecido en VB6 a los miembros compartidos de Visual Basic 2005 son
los mtodos y campos declarados en un mdulo .BAS.
Del mbito, la accesibilidad y los miembros compartidos nos ocuparemos con ms detalle en
una leccin posterior, donde veremos ciertas peculiaridades, como puede ser la limitacin del
mbito de un miembro que aparentemente tiene una accesibilidad no restringida.
Suma = n1 + n2
End Function
t = Suma(1, 3)
' 2- Indicando solamente el primer parmetro (el resultado ser 16= 1 + 15)
t = Suma(1)
32
t = Suma(1, n2:= 9)
Nota:
Los parmetros opcionales deben aparecer en la lista de parmetros del mtodo,
despus de los "obligatorios"
Dim i As Long
Dim j As Long
'
For i = 0 To UBound(n)
If IsArray(n(i)) Then
33
Next
Else
End If
Next
Suma = total
End Function
Dim t As Long
t = Suma(a, 4, 5, 6)
MsgBox(t)
Para usar este cdigo en Visual Basic 2005 tendremos que desactivar Option Strict y cambiar
el tipo Variant por Object, (cosa que el IDE har automticamente si pegamos el cdigo), lo
dems se puede quedar igual, incluso los tipos de datos, aunque debemos recordar que un
Long de VB6 es un Integer de VB2005.
Pero como no debemos "acostumbrarnos" a desactivar Option Strict, vamos a ver el cdigo
"bueno" de Visual Basic 2005, aunque no nos permita usar un array en los parmetros al
llamar a la funcin.
Function Suma(ByVal ParamArray n() As Integer) As Integer
34
total += CInt(n(i))
Next
Return total
End Function
'
MsgBox(t)
Nota:
Cuando queramos usar ParamArray para recibir un array de parmetros
opcionales, esta instruccin debe ser la ltima de la lista de parmetros de la
funcin (mtodo).
Tampoco se permite tener parmetros opcionales y ParamArray en la misma
funcin.
35
Supongamos que queremos tener dos funciones (o ms) que nos permitan hacer operaciones
con diferentes tipos de datos, y que, segn el tipo de datos usado, el valor que devuelva sea
de ese mismo tipo. En VB6 es imposible hacer esto. Salvo que creemos dos funciones con
nombres diferentes, pero en ese caso ya no estaremos usando la sobrecarga.
En este ejemplo, tenemos dos funciones que se llaman igual pero una recibe valores de tipo
entero y la otra de tipo decimal:
Function Suma(n1 As Integer, n2 As Integer) As Integer
Return n1 + n2
End Function
Return n1 + n2
End Function
Como podemos comprobar las dos funciones tienen el mismo nombre, pero tanto una como
otra reciben parmetros de tipos diferentes.
Con Visual Basic 2005 podemos sobrecargar funciones, pero lo interesante no es que
podamos hacerlo, sino cmo podemos usar esas funciones. En el cdigo anterior tenemos dos
funciones llamadas Suma, la primera acepta dos parmetros de tipo Integer y la segunda de
tipo Double. Lo interesante es que cuando queramos usarlas, no tenemos que preocuparnos
de cual vamos a usar, ya que ser el compilador el que decida la ms adecuada al cdigo que
usemos, por ejemplo:
' En este caso, se usar la que recibe dos valores enteros
El compilador de Visual Basic 2005 es el que decide que funcin usar, esa decisin la toma a
partir de los tipos de parmetros que hayamos indicado. En el segundo ejemplo de uso, el que
mejor coincide es el de los dos parmetros de tipo Double.
Tambin podemos tener sobrecarga usando una cantidad diferente de parmetros, aunque
stos sean del mismo tipo. Por ejemplo, podemos aadir esta declaracin al cdigo anterior
sin que exista ningn tipo de error, ya que esta nueva funcin recibe tres parmetros en lugar
de dos:
36
Return n1 + n2 + n3
End Function
Por tanto, cuando el compilador se encuentre con una llamada a la funcin Suma en la que se
usen tres parmetros, intentar usar esta ltima.
Nota:
Para que exista sobrecarga, la diferencia debe estar en el nmero o en el tipo de
los parmetros, no en el tipo del valor devuelto.
Cuando, desde el IDE de Visual Basic 2005, queremos usar los mtodos sobrecargados, nos
mostrar una lista de opciones indicndonos las posibilidades de sobrecarga que existen y
entre las que podemos elegir, tal como vemos en la figura 1.10:
Tal como comentbamos hace unas lneas, en VB6 se puede simular la sobrecarga mediante
los parmetros opcionales, aunque realmente no es lo mismo. Pero esa "simulacin" nos viene
como anillo al dedo para dar un consejo o advertencia: Cuidado con las funciones que
reciben parmetros opcionales, ya que el compilador puede producir un error si esa
funcin entra en conflicto con otra "sobrecargada"!
Mejor lo vemos con un ejemplo:
Function Suma(n1 As Integer, Optional n2 As Integer = 33) As Integer
Return n1 + n2
End Function
37
Nota:
Hay que tener en cuenta que si pasamos un objeto a una funcin, da igual que
lo declaremos por valor o por referencia, ya que en ambos casos se pasa una
referencia a la direccin de memoria en la que estn los datos, porque, como
sabemos, las variables de los tipos por referencia siempre contienen una
referencia a los datos, no los datos en s.
Nota:
Si usamos el IDE de Visual Basic 2005 Express para escribir el cdigo, no
debemos preocuparnos de este detalle, ya que si no indicamos si es por valor o
por referencia, automticamente le aadir la palabra clave ByVal, para que no
haya ningn tipo de dudas.
38
Con esta lnea de cdigo lo que estamos indicando al Visual Basic es que tenemos intencin
de usar una variable llamada c para acceder a una clase de tipo Cliente. Esa variable, cuando
llegue el momento de usarla, sabr todo lo que hay que saber sobre una clase Cliente, pero
hasta que no tenga una "referencia" a un objeto de ese tipo no podremos usarla.
La asignacin de una referencia a un objeto Cliente podemos hacerla de dos formas
distintas:
La primera es creando un nuevo objeto en la memoria:
c = New Cliente
Nota:
En VB6 esta forma de crear un nuevo objeto producira un error, ya que para
"asignar" a una variable un nuevo objeto tenemos que usar la instruccin Set,
en Visual Basic 2005 ya no es necesario el uso de esa instruccin, de hecho si la
usamos, recibiremos un error.
A partir de este momento, la variable c tiene acceso a un nuevo objeto del tipo Cliente, por
tanto podremos usarla para asignarle valores y usar cualquiera de los miembros que ese tipo
de datos contenga:
c.Nombre = "Antonio"
O tambin:
Dim c As Cliente = New Cliente
Las dos formas producen el mismo resultado, por tanto es recomendable usar la primera.
En VB6 este tipo de declaracin y asignacin no era recomendable, ya que aade trabajo
extra al compilador de VB. Ese trabajo extra consiste en comprobar si el objeto al que
queremos acceder ya est creado, en caso de que no sea as, primero lo crea y despus lo
usa, el inconveniente es que todas estas comprobaciones las realiza cada vez que usemos la
variable!
En Visual Basic 2005 este comportamiento ya no es as, el objeto se crea en la memoria y se
asigna a la variable, a partir de ese momento no se comprueba si ya est creado o no, ya que
se supone que s est creado.
39
Lo que debemos tener muy presente es que adems de la sobrecarga de trabajo que aade
VB6 a este tipo de instanciacin, el comportamiento es muy diferente al de Visual Basic 2005.
Por ejemplo, si en VB6 asignamos un valor nulo a una variable declarada de esta forma y acto
seguido usamos la variable, el motor en tiempo de ejecucin (runtime) crea un nuevo objeto
y asunto arreglado. Pero en Visual Basic 2005, si asignamos un valor nulo a una variable, le
estamos diciendo al CLR (el runtime de .NET) que ya no queremos usar ms ese objeto, por
tanto lo elimina de la memoria; si despus queremos volver a usar la variable, debemos crear
otro objeto, (con New), de no hacerlo, se producir un error, ya que en Visual Basic 2005 no
existe la auto-instanciacin.
'
FechaCreacion = Date.Now
End Sub
End Class
De esta forma podemos crear un nuevo Cliente y acto seguido comprobar el valor del campo
FechaCreacion para saber la fecha de creacin del objeto.
40
En los constructores tambin podemos hacer las inicializaciones que, por ejemplo permitan a
la clase a conectarse con una base de datos, abrir un fichero o cargar una imagen grfica,
etc., aunque en algunos de estos casos nos facilitar la tarea una nueva caracterstica que
VB6 no tiene.
Constructores parametrizados
De la misma forma que podemos tener mtodos y propiedades sobrecargadas, tambin
podemos tener constructores sobrecargados, ya que debemos recordar que en Visual Basic
2005, un constructor realmente es un mtodo de tipo Sub, y como todos los mtodos y
propiedades de Visual Basic 2005, tambin admite la sobrecarga.
La ventaja de tener constructores que admitan parmetros es que podemos crear nuevos
objetos indicando algn parmetro, por ejemplo un fichero a abrir o, en el caso de la clase
Cliente, podemos indicar el nombre y apellidos del cliente o cualquier otro dato que creamos
conveniente.
Para comprobarlo, podemos ampliar la clase definida anteriormente para que tambin acepte
la creacin de nuevos objetos indicando el nombre y los apellidos del cliente.
Class Cliente
'
FechaCreacion = Date.Now
End Sub
'
Nombre = elNombre
Apellidos = losApellidos
FechaCreacion = Date.Now
41
End Sub
End Class
Teniendo esta declaracin de la clase Cliente, podemos crear nuevos clientes de dos formas:
Dim c1 As New Cliente
'
FechaCreacion = Date.Now
End Sub
'
New()
42
Nombre = elNombre
Apellidos = losApellidos
End Sub
End Class
Es decir, desde el constructor con argumentos llamamos al constructor que no los tiene,
consiguiendo que tambin se asigne la fecha.
Esta declaracin de la clase Cliente realmente no compilar. Y no compila por la razn tan
"simple" de que aqu el compilador de Visual Basic 2005 no sabe cual es nuestra intencin, ya
que New es una palabra reservada que sirve para crear nuevos objetos y, siempre, una
instruccin tiene preferencia sobre el nombre de un mtodo, por tanto, podemos recurrir al
objeto especial Me el cual nos sirve, al igual que en VB6, para representar al objeto que
actualmente est en la memoria, as que, para que esa declaracin de la clase Cliente
funcione, debemos usar Me.New() para llamar al constructor sin parmetros.
Nota:
El IDE de Visual Basic 2005 colorea las instrucciones y tipos propios del
lenguaje, tal y como lo hace el de VB6, en el caso de Me, VB6 no la colorea, pero
este no es el motivo de esta nota, lo que no debe confundirnos es que cuando
declaramos Sub New, tanto Sub como New se muestran coloreadas, cuando solo
se debera colorear Sub; sin embargo cuando usamos Me.New, solo se colorea
Me y no New que es correcto, tal como vemos en la figura 1.11, ya que en este
caso New es el nombre de un procedimiento y los procedimientos no son parte
de las instrucciones y tipos de .NET.
43
Pero hay ocasiones en las que nos puede interesar que no exista un constructor sin
parmetros, por ejemplo, podemos crear una clase Cliente que solo se pueda instanciar si le
pasamos, por ejemplo el nmero de identificacin fiscal, (NIF), en caso de que no se indique
ese dato, no podremos crear un nuevo objeto Cliente, de esta forma, nos aseguramos
siempre de que el NIF siempre est especificado. Seguramente por ese motivo, si nosotros
definimos un constructor con parmetros, Visual Basic 2005 no crea uno automticamente sin
parmetros. Por tanto, si definimos un constructor con parmetros en una clase y queremos
que tambin tenga uno sin parmetros, lo tenemos que definir nosotros mismos.
Recomendacin:
Si nuestra clase utiliza recursos externos, por ejemplo un fichero o una base de
datos, debemos definir un mtodo que se encargue de liberarlos y a ese mtodo
debemos encargarnos de llamarlo cuando ya no lo necesitemos.
Por definicin a este tipo de mtodos se les suele dar el nombre Close o Dispose,
aunque este ltimo tiene un significado especial y por convencin solo debemos
usarlo siguiendo las indicaciones de la documentacin.
44
instruccin es: Structure, por eso en Visual Basic 2005 a los tipos por valor definidos por el
usuario se llaman estructuras.
Nota:
El equivalente en VB6 a una estructura de Visual Basic 2005 es Type, aunque es
solo eso: un parecido, pero realmente no es equivalente, al menos al 100%, tal
como tendremos oportunidad de comprobar en esta leccin.
Las estructuras pueden contener los mismos miembros que las clases, aunque algunos de
ellos se comporten de forma diferente o al menos tengan algunas restricciones, como que los
campos definidos en las estructuras no se pueden inicializar al mismo tiempo que se declaran
o no pueden contener constructores "simples", ya que el propio compilador siempre se
encarga de crearlo, para as poder inicializar todos los campos definidos.
Otra de las caractersticas de las estructuras es que no es necesario crear una instancia para
poder usarlas, ya que es un tipo por valor y los tipos por valor no necesitan ser instanciados
para que existan.
Public X As Integer
Public Y As Integer
End Structure
p.X = 100
p.Y = 75
Aunque en las estructuras, usar New, sera algo redundante y por tanto no necesario.
45
Las estructuras siempre se almacenan en la pila, por tanto deberamos tener la precaucin de
no crear estructuras con muchos campos o con muchos miembros, ya que esto implicara un
mayor consumo del "preciado" espacio de la pila.
Public X As Integer
Public Y As Integer
'
Me.X = x
Me.Y = y
End Sub
End Structure
Nota:
Tanto en las estructuras como en las clases podemos tener constructores
compartidos, en el caso de las estructuras, este tipo de constructor es el nico
que podemos declarar sin parmetros.
46
Campos
Como vimos, las variables declaradas a nivel del tipo, son los campos, la principal diferencia
con respecto a las clases, es que los campos de una estructura no pueden inicialiarse en la
declaracin y el valor que tendrn inicialmente es un valor "nulo", que en el caso de los
campos de tipo numricos es un cero.
Por tanto, si necesitamos que los campos tengan algn valor inicial antes de usarlos,
deberamos indicarlo a los usuarios de nuestra estructura y proveer un constructor que realice
las inicializaciones correspondientes, pero debemos recordar que ese constructor debe tener
algn parmetro, ya que el predeterminado sin parmetros no podemos "reescribirlo".
Los nicos campos que podemos inicializar al declararlos son los campos compartidos, pero
como tendremos oportunidad de ver, estos campos sern accesibles por cualquier variable
declarada y cualquier cambio que realicemos en ellos se ver reflejado en el resto de
"instancias" de nuestro tipo.
47
Esta caracterstica de las estructuras nos permite hacer copias "reales" no copia de la
referencia (o puntero) al objeto en memoria como ocurre con los tipos por referencia.
Vemoslos con un ejemplo.
Dim p As New Punto(100, 75)
Dim p1 As Punto
p1 = p
p1.X = 200
En este trozo de cdigo definimos e instanciamos una variable del tipo Punto, a continuacin
declaramos otra variable del mismo tipo y le asignamos la primera, si estos tipos fuesen por
referencia, tanto una como la otra estaran haciendo referencia al mismo objeto en memoria,
y cualquier cambio realizado a cualquiera de las dos variables afectaran al mismo objeto,
pero en el caso de las estructuras (y de los tipos por valor), cada cambio que realicemos se
har sobre un objeto diferente, por tanto la asignacin del valor 200 al campo X de la
variable p1 solo afecta a esa variable, dejando intacto el valor original de la variable p.
Accesibilidad y mbito
Tal y como comentamos anteriormente, dependiendo de dnde y cmo estn declarados los
tipos de datos y los miembros definidos en ellos, tendremos o no acceso a esos elementos.
Recordemos que el mbito es el alcance con el que podemos acceder a un elemento y
depende de dnde est declarado, por otro lado, la accesibilidad depende de cmo
declaremos cada uno de esos elementos.
mbito
Dependiendo de donde declaremos un miembro o un tipo, ste tendr mayor alcance o
cobertura, o lo que es lo mismo, dependiendo del mbito en el que usemos un elemento,
podremos acceder a l desde otros puntos de nuestro cdigo.
A continuacin veremos con detalle los mbitos en los que podemos declarar los distintos
elementos de Visual Basic 2005.
48
Nota:
Por regla general, cuando declaramos una variable en un mbito, dicha variable
"ocultar" a otra que tenga el mismo nombre y est definida en un bloque con
mayor alcance, aunque veremos que en Visual Basic 2005 existen ciertas
restricciones dependiendo de dnde declaremos esas variables.
En VB6 los mbitos disponibles solamente eran los de mdulo y procedimiento, en estos
casos, cualquier variable declarada en un procedimiento oculta a una definida en un mdulo.
En Visual Basic 2005 podemos definir una variable dentro de un bloque de cdigo, en ese
caso dicha variable solo ser accesible dentro de ese bloque. Aunque, como veremos a
continuacin, en un procedimiento solamente podremos definir variables que no se oculten
entre s, estn o no dentro de un bloque de cdigo.
mbito de bloque
En los siguientes ejemplos veremos cmo podemos definir variables para usar solamente en
el bloque en el que estn definidas.
Los bloques de cdigo en los que podemos declarar variables son los bucles, (For, Do, While),
y los bloques condicionales, (If, Select).
Por ejemplo, dentro de un procedimiento podemos tener varios de estos bloques y por tanto
podemos definir variables "internas" a esos bloques:
Dim n As Integer = 3
'
For i As Integer = 1 To 10
Dim j As Integer
j += 1
If j < n Then
'...
End If
49
Next
'
If n < 5 Then
Dim j As Integer = n * 3
End If
'
Do
Dim j As Integer
For i As Integer = 1 To n
j += i
Next
Loop
La variable n estar disponible en todo el procedimiento, por tanto podemos acceder a ella
desde cualquiera de los bloques.
En el primer bucle For, definimos la variable i como la variable a usar de contador, esta
variable solamente estar accesible dentro de este bucle For. Lo mismo ocurre con la variable
j.
En el primer If definimos otra variable j, pero esa solo ser accesible dentro de este bloque If
y por tanto no tiene ninguna relacin con la definida en el bucle For anterior.
En el bucle Do volvemos a definir nuevamente una variable j, a esa variable la podemos
acceder solo desde el propio bucle Do y cualquier otro bloque de cdigo interno, como es el
caso del bucle For, en el que nuevamente declaramos una variable llamada i, que nada tiene
que ver con el resto de variables declaradas con el mismo nombre en los otros bloques.
Lo nico que no podemos hacer en cualquiera de esos bloques, es declarar una variable
llamada n, ya que al estar declarada en el procedimiento, el compilador de Visual Basic 2005
nos indicar que no podemos ocultar una variable previamente definida fuera del bloque, tal
como podemos ver en la figura 1.12.
50
mbito de procedimiento
Las variables declaradas en un procedimiento tendrn un mbito o cobertura que ser el
procedimiento en el que est declaradas, y como hemos visto, ese mbito incluye tambin
cualquier bloque de cdigo declarado dentro del procedimiento.
Estas variables ocultarn a las que se hayan declarado fuera del procedimiento, si bien,
dependiendo del tipo de mdulo, podremos acceder a esas variables "externas" indicando el
nombre completo del mdulo o bien usando la instruccin Me, tal como vimos en el cdigo del
constructor parametrizado de la estructura Punto.
Pero mejor vemoslo con un ejemplo. En el siguiente cdigo, definimos una clase en la que
tenemos un campo llamado Nombre, tambin definimos un mtodo en el que internamente
se utiliza una variable llamada nombre, para acceder a la variable declarada en la clase,
tendremos que usar la instruccin o palabra clave Me.
Public Class Cliente
Return "Externo= " & Me.Nombre & ", interno= " & nombre
End Function
End Class
En este ejemplo, el hecho de que una variable est declarada con la letra ene en mayscula o
en minscula no implica ninguna diferencia, ya que Visual Basic 2005 al igual que VB6 no
hace distinciones de este tipo, si bien, en Visual Basic 2005 no se cambia automticamente el
"case" de las variables, salvo cuando estn en el mismo nivel de mbito; en cambio, si en VB6
declaramos una variable con el mismo nombre, aunque est en un mbito diferente, siempre
se usar el estado de maysculas/minsculas de la ltima definicin.
51
mbito de mdulo
Cuando hablamos de mdulos, nos estamos refiriendo a una clase, a una estructura o a
cualquier otro tipo de datos que nos permita .NET.
En estos casos, las variables declaradas dentro de un tipo de datos sern visibles desde
cualquier parte de ese tipo, siempre teniendo en cuenta las restricciones mencionadas en los
casos anteriores.
Class Cliente
End Class
End Namespace
El problema es que el compilador de Visual Basic 2005 nos indicar que el tipo Int32 no est
definido, ya que intentar buscarlo dentro del mbito que actualmente tiene, es decir, la
declaracin que nosotros hemos hecho de System, por tanto para poder acceder al tipo Int32
definido en el espacio de nombres "global" System de .NET tendremos que usar la instruccin
Global, por suerte el IDE de Visual Basic 2005 Express reconoce este tipo de error y nos
ofrece ayuda para poder solventar el conflicto, tal como vemos en la figura 1.13:
52
Figura 1.13. Ayuda del IDE en los conflictos de espacios nombres globales
Nota:
Afortunadamente este conflicto con los espacios de nombres no ser muy
habitual para los desarrolladores que usemos el idioma de Cervantes, por la
sencilla razn de que los espacios de nombres de .NET Framework suelen estar
definidos usando palabras en ingls.
Accesibilidad
La accesibilidad es la caracterstica que podemos aplicar a cualquiera de los elementos que
definamos en nuestro cdigo. Dependiendo de la accesibilidad declarada tendremos distintos
tipos de accesos a esos elementos.
Los modificadores de accesibilidad que podemos aplicar a los tipos y elementos definidos en
nuestro cdigo pueden ser cualquiera de los mostrados en la siguiente lista:
Friend: Acceso limitado al proyecto actual. Visual Basic 2005 aplica este
modificador de forma predeterminada a los procedimientos declarados en las
clases.
53
Nota:
La palabra clave Static, tiene el mismo significado que en VB6, y nos permite
definir una variable privada (o local) al procedimiento para que mantenga el
valor entre diferentes llamadas a ese procedimiento; esto contrasta con el resto
de variables declaradas en un procedimiento cuya duracin es la misma que la
vida del propio procedimiento, por tanto, las variables no estticas pierden el
valor al terminar la ejecucin del procedimiento.
del tipo
de las variables
declaradas con
Dim
de los
procedimientos
Class
Friend
Private
Friend
Module
Friend
Private
Friend
Structure
Friend
Public
Public
Enum
Public
Friend
N.A.
(los miembros
siempre son
pblicos)
N.A.
Interface
Friend
N.A.
Public
(no se pueden
(no se permite
declarar variables) indicarlo)
54
En esta otra tabla tenemos la accesibilidad permitida en cada tipo as como las que podemos
indicar en los miembros de esos tipos.
Tipo
del tipo
de los miembros
Class
Public
Friend
Private
Protected
Protected Friend
Public
Friend
Private
Protected
Protected Friend
Module
Public
Friend
Public
Friend
Private
Structure
Public
Friend
Private
Public
Friend
Private
Enum
Public
Friend
Private
N.A.
Interface
Public
Friend
Private
Protected
Protected Friend
N.A.
Siempre son pblicos
Anidacin de tipos
Tal como hemos comentado en el prrafo anterior, podemos declarar tipos dentro de otros
tipos, por tanto el mbito y accesibilidad de esos tipos dependen del mbito y accesibilidad
del tipo que los contiene. Por ejemplo, si declaramos una clase con acceso Friend, cualquier
tipo que esta clase contenga siempre estar supeditado al mbito de esa clase, por tanto si
declaramos otro tipo interno, aunque lo declaremos como Public, nunca estar ms accesible
que la clase contenedora, aunque en estos casos no habr ningn tipo de confusin, ya que
para acceder a los tipos declarados dentro de otros tipos siempre tendremos que indicar la
clase que los contiene.
En el siguiente cdigo podemos ver cmo declarar dos clases "anidadas". Tal como podemos
comprobar, para acceder a la clase Salario debemos indicar la clase Cliente, ya que la nica
forma de acceder a una clase anidada es mediante la clase contenedora.
Friend Class Cliente
55
End Class
End Class
s.Importe = 2200
Nota:
Los espacios de nombres tambin pueden anidarse y contener a su vez
cualquiera de los tipos mostrados en la tabla 1.4, incluso tipos Module.
56
para poder hacerlo debemos indicar el nombre completo, ya que en caso contrario, el
compilador de Visual Basic 2005 sera incapaz de saber a que clase queremos acceder.
Namespace Uno
End Class
End Namespace
Namespace Dos
Sub Main()
c1.Nombre = "Pepe"
End Sub
End Class
End Namespace
Esto mismo lo podemos aplicar en el caso de que tengamos dos clases con el mismo nombre
en espacios de nombres distintos.
Nota:
En el mismo proyecto podemos tener ms de una declaracin de un espacio de
nombres con el mismo nombre, en estos casos el compilador lo tomar como si
todas las clases definidas estuvieran dentro del mismo espacio de nombres,
aunque estos estn definidos en ficheros diferentes.
57
De esta forma podemos usar el "alias" vb para acceder a las clases y dems tipos definidos
en ese espacio de nombres.
En las figuras 1.14 1.15 podemos ver las dos formas de acceder a las clases del espacio de
ese espacio de nombres, en el primer caso sin usar un alias y en el segundo usando el alias
vb.
58
Propiedades
Las propiedades son los miembros de los tipos que nos permiten acceder a los datos que
dicho tipo manipula. Normalmente una propiedad est relacionada con un campo, de forma
que el campo sea el que realmente contenga el valor y la propiedad simplemente sea una
especie de mtodo a travs del cual podemos acceder a ese valor.
Debido a que el uso de las propiedades realmente nos permite acceder a los valores de una
clase (o tipo), se suelen confundir los campos con las propiedades, de hecho en VB6 si
definimos una variable pblica, sta se convierte en una propiedad de la clase, en Visual Basic
2005 casi ocurre lo mismo, pero realmente un campo (o variable) pblico no es una
propiedad, al menos en el sentido de que el propio .NET Framework no lo interpreta como tal,
aunque en la prctica nos puede parecer que es as, ya que se utilizan de la misma forma.
Pero no debemos dejarnos llevar por la comodidad y si no queremos perder funcionalidad,
debemos diferenciar en nuestro cdigo las propiedades de los campos.
Lo primero que debemos tener presente es que gracias a esta diferenciacin que hace .NET
Framework, (realmente VB6 tambin la hace), podemos poner en prctica una de las
59
Nota:
En VB6 realmente disponemos de tres bloques o partes en la definicin de una
propiedad:
Property Get, que nos permite acceder al valor de la propiedad.
Propery Let, que nos permite asignar un valor a la propiedad.
Property Set, el cual lo usamos cuando la propiedad representa un objeto y
queremos asignar dicho objeto a la propiedad.
La diferencia entre Let y Set es que el primero se usar en valores de tipos por
valor y el segundo en tipos por referencia, aunque el compilador de VB6
realmente usar uno u otro segn asignemos el valor directamente a la
propiedad o usemos la instruccin Set para hacer esa asignacin.
Tal como indicamos en la nota anterior, en VB6 existen dos formas de asignar valores a una
propiedad de una clase, pero en Visual Basic 2005 no existe ese "conflicto" en la forma de
asignar los valores, ya que siempre que se asigna un valor a una propiedad se hace sin usar
la instruccin Set, de hecho no se puede usar Set para realizar asignaciones a propiedades en
VB2005.
Veamos como definir una propiedad en Visual Basic 2005:
Public Class Cliente
60
Get
Return _nombre
End Get
_nombre = value
End Set
End Property
End Class
Como podemos comprobar tenemos dos bloques de cdigo, el bloque Get que es el que se
usa cuando queremos acceder al valor de la propiedad, por tanto devolvemos el valor del
campo privado usado para almacenar ese dato. El bloque Set es el usado cuando asignamos
un valor a la propiedad, este bloque tiene definido un parmetro (value) que representa al
valor que queremos asignar a la propiedad.
Aunque en Visual Basic 2005 las definiciones para obtener o asignar el valor de la propiedad
se hacen en bloques definidos dentro de un procedimiento del tipo Property, esta forma de
definir las propiedades no se diferencia demasiado a como lo hacemos en VB6, y una vez que
nos acostumbremos lo veremos como una forma ms "compacta" de hacerlo.
Get
Return Date.Now
61
End Get
End Property
' ok
End If
End Set
End Property
Get
62
Return _salario
End Get
_salario = value
End Set
End Property
End Class
Para hacer que el bloque Set sea privado, lo indicamos con el modificador de accesibilidad
Private, al no indicar ningn modificador en el bloque Get, ste ser el mismo que el de la
propiedad.
En VB6 podemos hacer esto mismo definiendo como pblico la declaracin de Property Get y
como privado la de la asignacin: Property Let.
Nota:
El nivel de accesibilidad de los bloques Get o Set debe ser igual o inferior que el
de la propiedad, por tanto si la propiedad la declaramos como Private, no
podemos definir como pblico los bloques Get o Set.
Propiedades predeterminadas
Una cosa que echamos en falta en Visual Basic 2005 son las propiedades predeterminadas,
aunque existen no son exactamente igual que en VB6. En VB6 podemos definir como
propiedad predeterminada cualquiera de las propiedades de la clase, aunque la forma de
hacerlo es un poco "rebuscada" y poco intuitiva, al menos podemos definir como
predeterminada la que ms nos interese. En Visual Basic 2005 no podemos definir como
predeterminada cualquier propiedad, ya que debido a como se realizan las asignaciones de
objetos en .NET (sin necesidad de usar Set), siempre debemos indicar la propiedad a la que
queremos asignar el valor, porque en caso de que no se indique ninguna, el compilador
interpretar que lo que queremos asignar es un objeto y no un valor a una propiedad.
Para evitar conflictos o tener que usar alguna instruccin "extra" para que se sepa si lo que
queremos asignar es un valor o un objeto, en Visual Basic 2005 las propiedades
predeterminadas siempre deben ser parametrizadas, es decir, tener como mnimo un
parmetro.
Para indicar que una propiedad es la propiedad por defecto lo debemos hacer usando la
instruccin Default:
Default Public ReadOnly Property Item(ByVal index As Integer) As Empleado
63
Get
' ...
End Get
End Property
Como vemos en este ejemplo, una propiedad por defecto puede ser de solo lectura y tambin
de solo escritura o de lectura/escritura.
Para usar esta propiedad, al ser la propiedad por defecto, no es necesario indicar el nombre
de la propiedad, aunque si as lo deseamos podemos indicarla, aunque en este caso no
tendra mucha utilidad el haberla definido como propiedad por defecto:
Dim e As New Empleado
Get
' ...
End Get
End Property
64
Get
' ...
End Get
'
End Set
End Property
Incluso como vemos en este cdigo una de las sobrecargas puede ser de solo lectura y la otra
de lectura/escritura. Lo que realmente importa es que el nmero o tipo de parmetros de
cada sobrecarga sea diferente.
Las propiedades predeterminadas tienen sentido en Visual Basic 2005 cuando queremos que
su uso sea parecido al de un array. Por tanto es habitual que las clases de tipo coleccin sean
las ms indicadas para definir propiedades por defecto. Aunque no siempre el valor devuelto
debe ser un elemento de una coleccin o array, ya que podemos usar las propiedades
predeterminadas para acceder a los miembros de una clase "normal", de forma que se
devuelva un valor segn el parmetro indicado, esto nos permitira, por ejemplo, acceder a
los miembros de la clase desde un bucle For. Si definimos una propiedad predeterminada
como en el siguiente cdigo:
Public Class Articulo
Get
Case 0
Return Descripcin
65
Case 1
Return PrecioVenta.ToString
Case 2
Return Existencias.ToString
Case Else
Return ""
End Select
End Get
End Property
End Class
Console.WriteLine( art(i) )
Next
Resumiendo:
Las propiedades predeterminadas en Visual Basic 2005 siempre deben tener un parmetro,
para que su uso se asemeje a un array, es decir, se use como indizador de la clase. Por
convencin, cuando se usan como indizador, el nombre de la propiedad predeterminada suele
ser Item.
Interfaces
Las interfaces son un elemento bastante importante en .NET Framework, ya que de hecho se
utiliza con bastante frecuencia, en esta leccin veremos que son las interfaces y como
utilizarlas en nuestros proyectos, tambin veremos que papel juegan en .NET y cmo aplicar
algunas de las definidas en la biblioteca base.
66
Qu es una interfaz?
Las interfaces son una forma especial de una clase, aunque la diferencia principal con las
clases es que las interfaces no contienen cdigo ejecutable, solo definen los miembros.
Para entenderlo mejor, veamos las interfaces desde el punto de vista de Visual Basic 6.0.
En Visual Basic 6.0, cuando definimos una clase, realmente estamos haciendo dos cosas:
1- Definiendo una interfaz con cada uno de los miembros que la clase contiene: mtodos,
propiedades, eventos, etc.
2- Definiendo el cdigo a utilizar por cada uno de esos miembros.
Desde ese punto de vista, podemos decir que una interfaz define cada uno de los miembros
de una clase, es decir, que tipo de mtodo es, si los mtodos tienen parmetros, cuantos y de
que tipos son, que propiedades o eventos define la clase, etc.
Por tanto, podemos decir que la interfaz de una clase indica los miembros que dicha clase
expone, y como hemos indicado anteriormente, cuando en VB6 definimos una clase, tambin
estamos definiendo una interfaz, de hecho en Visual Basic 6.0 no hay forma de definir
interfaces como algo independiente de una clase; cuando queremos definir una interfaz en
VB6, lo ms que podemos hacer es definir una clase sin cdigo ejecutable.
Pero Visual Basic 2005, va an ms lejos, ya que las interfaces las definimos de forma
independiente de las clases. Es ms, cuando definimos una clase NO estamos definiendo una
interfaz.
Para definir una interfaz en VB2005 tenemos que usar la instruccin Interface seguida del
nombre y acabar la declaracin con End Interface:
Public Interface IAnimal
'...
End Interface
Nota:
Segn las indicaciones de nomenclatura de .NET Framework, se recomienda que
todas las interfaces empiecen con una I mayscula seguida del nombre al que
hacer referencia la interfaz.
67
Sub Mostrar()
Event DatosCambiados()
End Interface
El primer miembro de esta interfaz, es un mtodo de tipo Sub que no recibe parmetros.
El siguiente mtodo es una funcin que devuelve un valor de tipo String y recibe un
parmetro tambin de tipo cadena.
A continuacin definimos una propiedad que devuelve una cadena.
Por ltimo, definimos un evento.
Como podemos observar, lo nico que tenemos que hacer es indicar el tipo de miembro y si
recibe o no algn parmetro o argumento.
Dos cosas importantes sobre las interfaces:
1- No se pueden definir campos.
2- Los miembros de las interfaces siempre son pblicos, tal como indicbamos en la tabla 1.3.
68
Implements IPrueba
Y como comentbamos, cualquier clase que implemente una interfaz debe definir cada uno de
los miembros de esa interfaz, por eso es el propio Visual Basic el encargado de crear
automticamente los mtodos y propiedades que la interfaz implementa, aunque solo inserta
el "prototipo" de cada uno de esos miembros, dejando para nosotros el trabajo de escribir el
cdigo.
Usando la definicin de la interfaz IPrueba que vimos antes, el cdigo que aadir VB ser el
siguiente:
Public Class Prueba
Implements IPrueba
End Sub
Get
End Get
69
End Set
End Property
Implements IPrueba.Saludo
End Function
End Class
Como podemos apreciar, no solo ha aadido las definiciones de cada miembro de la interfaz,
sino que tambin aade cdigo extra a cada uno de esos miembros: la instruccin
Implements seguida del nombre de la interfaz y el miembro al que se har referencia.
Nota:
Si el lector antes ha utilizado las interfaces en VB6, esto no le resultar extrao,
ya que en ese lenguaje, cuando implementamos una interfaz tambin se crean
automticamente las definiciones de los miembros que contiene la interfaz,
aunque el formato utilizado por VB6 es: <Nombre de la interfaz> <guin bajo>
<nombre del mtodo>, por ejemplo: Private Sub IPrueba_Mostrar().
La utilidad de que en cada uno de los miembros se indique expresamente el mtodo al que se
hace referencia, es que podemos usar nombres diferentes al indicado en la interfaz. Por
ejemplo, si implementamos esta interfaz en una clase que solo utilizar la impresora, al
mtodo Mostrar lo podramos llamar Imprimir que sera ms adecuado, en ese caso
simplemente cambiamos el nombre del mtodo de la clase para que implemente el mtodo
Mostrar de la interfaz:
Public Sub Imprimir() Implements IPrueba.Mostrar
End Sub
70
De esta forma, aunque en la clase se llame de forma diferente, realmente hace referencia al
mtodo de la interfaz.
prueba1.Mostrar()
O bien de forma indirecta, por medio de una variable del mismo tipo que la interfaz:
Dim prueba1 As New Prueba
interfaz1 = prueba1
interfaz1.Mostrar()
Qu ha ocurre aqu?
Como ya comentamos anteriormente, cuando asignamos variables por referencia, realmente
lo que asignamos son referencias a los objetos creados en la memoria, por tanto la variable
interfaz1 est haciendo referencia al mismo objeto que prueba1, aunque esa variable solo
tendr acceso a los miembros de la clase Prueba que conoce, es decir, los miembros definidos
en IPrueba.
Si la clase define otros miembros que no estn en la interfaz, la variable interfaz1 no podr
acceder a ellos.
71
interfaz1 = prueba1
interfaz1.Mostrar()
End If
Implements IPrueba
Implements IComparable
2- Indicando las otras interfaces en la misma instruccin Implements, pero separndolas con
comas:
Public Class Prueba
72
Sub Mostrar()
End Interface
End Sub
Aunque si ambos mtodos hacen lo mismo, en este ejemplo mostrar algo, podramos hacer
que el mismo mtodo de la clase sirva para implementar el de las dos interfaces:
Public Sub Mostrar() Implements IPrueba.Mostrar, IMostrar.Mostrar
End Sub
Es decir, lo nico que tendramos que hacer es indicar la otra implementacin separndola con
una coma.
Nota:
Cuando una interfaz implementa otras interfaces, stas no se pueden indicar
mediante Implements, en lugar de usar esa instruccin debemos usar Inherits.
Public Interface IPrueba2
Inherits IMostrar
73
Si en una clase implementamos una interfaz que a su vez implementa otras interfaces, esa
clase tendr definiciones de todos los miembros de todas las interfaces, por ejemplo, si
tenemos la siguiente definicin de la interfaz IPrueba2 que "implementa" la interfaz
IMostrar:
Public Interface IPrueba2
Inherits IMostrar
Event DatosCambiados()
End Interface
Implements IPrueba2
End Sub
Get
74
End Get
End Set
End Property
Implements IPrueba2.Saludo
End Function
End Class
En este cdigo, el mtodo Mostrar se indica mediante la interfaz IMostrar, pero tambin se
puede hacer por medio de IPrueba2.Mostrar, ya que IPrueba2 tambin lo implementa (o
hereda).
Si dejamos que Visual Basic cree los miembros, no tendremos problemas a la hora de
definirlos. Pero si lo hacemos manualmente, aunque dentro del IDE de Visual Basic, ste nos
ayuda indicndonos que interfaces implementamos y qu miembros son los que se adecuan a
la declaracin que estamos usando, tal como podemos comprobar en la figura 1.02.16:
Figura 1.02.16 IntelliSense solo muestra los mtodos que mejor se adecuan a la
declaracin
75
En el siguiente cdigo tenemos la definicin de una clase llamada Empleado que implementa
la interfaz IComparable y en el mtodo CompareTo hace la comprobacin de que objeto es
mayor o menor, si el de la propia clase o el indicado en el parmetro de esa funcin:
Public Class Empleado
Implements IComparable
Me.Nombre = nombre
End Sub
Implements System.IComparable.CompareTo
Else
Return 0
76
End If
End Function
End Class
En el mtodo CompareTo hacemos una comprobacin de que el objeto con el que debemos
realizar la comparacin es del tipo Empleado, en ese caso convertimos el objeto pasado en
uno del tipo Empleado y comparamos los nombres.
Si el objeto que recibe el mtodo no es del tipo Empleado, devolvemos un cero, para indicar
que no haga ninguna clasificacin, ya que ese valor indica que los dos objetos son iguales.
Esta comparacin no es estrictamente necesaria, ya que si no indicamos el valor que debe
devolver una funcin, devolver un valor cero, al menos en este caso, ya que el tipo a
devolver es un nmero entero.
Esta clase la podemos usar de esta forma:
' Una coleccin de datos del tipo Empleado.
empleados.Add(New Empleado("Pepe"))
empleados.Add(New Empleado("Bernardo"))
empleados.Add(New Empleado("Juan"))
empleados.Add(New Empleado("Ana"))
empleados.Sort()
Console.WriteLine(e1.Nombre)
77
Next
78
Excepciones
Introduccin
Es indiscutible que por mucho que nos lo propongamos, nuestras aplicaciones no estarn
libres de errores, y no nos referimos a errores sintcticos, ya que, afortunadamente, el IDE
(Integrated Development Envirnment, entorno de desarrollo integrado) de Visual Basic 2005
nos avisar de cualquier error sintctico e incluso de cualquier asignacin no vlida (al menos
si tenemos activado Option Strict On), pero de lo que no nos avisar, como es lgico, ser de
los errores que se produzcan en tiempo de ejecucin. Para estos casos, Visual Basic pone a
nuestra disposicin el manejo de excepciones, veamos pues cmo utilizarlo, sobre todo el
sistema de excepciones estructuradas que es el recomendable para cualquier desarrollo
con .NET Framework.
Manejo de excepciones
En Visual Basic 2005 el tratamiento de errores (excepciones) ha cambiado con respecto a
como lo hacemos en Visual Basic 6.0, ahora podemos usar un tratamiento de excepciones
estructurado, de esta forma podemos detectar los errores que se produzcan en nuestras
aplicaciones de una forma ms "ordenada".
En Visual Basic 6.0 la nica forma de detectar errores es usando On Error. Esta forma no
estructurada de tratar los errores se sigue soportando en Visual Basic 2005, pero a todas
luces no es la forma recomendada, si bien es cierto que debemos adaptar nuestra mente al
formato estructurado, ya que en un principio nos parecer que no es tan efectivo como On
Error.
En esta leccin veremos cmo tratar los errores de forma estructurada, ya que el "viejo" On
Error sigue funcionando de la misma forma que en VB6.
79
Cuando creamos una estructura de control de excepciones no estamos obligados a usar los
tres bloques, aunque el primero: Try si es necesario, ya que es el que le indica al compilador
que tenemos intencin de controlar los errores que se produzcan. Por tanto podemos crear un
"manejador" de excepciones usando los tres bloques, usando Try y Catch o usando Try y
Finally.
Veamos ahora con ms detalle cada uno de estos bloques y que es lo que podemos hacer en
cada uno de ellos.
Bloque Try
En este bloque incluiremos el cdigo en el que queremos comprobar los errores.
El cdigo a usar ser un cdigo normal, es decir, no tenemos que hacer nada en especial, ya
que en el momento que se produzca el error se usar (si hay) el cdigo del bloque Catch.
Bloque Catch
Si se produce una excepcin, sta la capturamos en un bloque Catch.
En el bloque Catch podemos indicar que tipo de excepcin queremos capturar, para ello
usaremos una variable de tipo Exception, la cual pude ser del tipo de error especfico que
queremos controlar o de un tipo genrico.
Por ejemplo, si sabemos que nuestro cdigo puede producir un error al trabajar con ficheros,
podemos usar un cdigo como este:
Try
Catch ex As System.IO.IOException
End Try
Si nuestra intencin es capturar todos los errores que se produzcan, es decir, no queremos
hacer un filtro con errores especficos, podemos usar la clase Exception como tipo de
excepcin a capturar. La clase Exception es la ms genrica de todas las clases para manejo
de excepciones, por tanto capturar todas las excepciones que se produzcan.
Try
Catch ex As Exception
End Try
80
Aunque si no vamos usar la variable indicada en el bloque Catch, pero queremos que no se
detenga la aplicacin cuando se produzca un error, podemos hacerlo de esta forma:
Try
Catch
End Try
Try
x = CInt(Console.ReadLine())
y = CInt(Console.ReadLine())
= x \ y
81
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
Bloque Finally
En este bloque podemos indicar las instrucciones que queremos que se ejecuten, se produzca
o no una excepcin. De esta forma nos aseguramos de que siempre se ejecutar un cdigo,
por ejemplo para liberar recursos, se haya producido un error o no.
Nota:
Hay que tener en cuenta de que incluso si usamos Exit Try para salir del bloque
de control de errores, se ejecutar el cdigo indicado en el bloque Finally.
Nota:
De los eventos nos ocuparemos en la siguiente leccin, pero como el evento
UnhandledException est directamente relacionado con la captura de errores, lo
mostramos en esta, aunque recomendamos al lector que esta seccin la vuelva a
leer despus de ver todo lo relacionado con los eventos.
82
Este evento se "dispara" cuando se produce un error que no hemos interceptado, por tanto
podramos usarlo para prevenir que nuestra aplicacin se detenga o bien para guardar en un
fichero .log la causa de dicho error para posteriormente actualizar el cdigo y prevenirlo. Ya
que cuando se produce el evento UnhandledException, podemos averiguar el error que se ha
producido e incluso evitar que la aplicacin finalice. Esa informacin la obtenemos mediante
propiedades expuestas por el segundo parmetro del evento, en particular la propiedad
Exception nos indicar el error que se ha producido y por medio de la propiedad
ExitApplication podemos indicar si terminamos o no la aplicacin.
Nota:
Cuando ejecutamos una aplicacin desde el IDE (entorno de desarrollo), los
errores no controlados siempre se producen, independientemente de que
tengamos o no definida la captura de errores desde el evento
UnhandledException. Ese evento solo se producir cuando ejecutemos la
aplicacin fuera del IDE de Visual Basic.
83
EVENTOS Y DELEGADOS
Introduccin
La forma que tienen nuestras clases y estructuras de comunicar que algo est ocurriendo, es
por medio de eventos. Los eventos no nos son desconocidos a los desarrolladores de Visual
Basic 6.0, ya que tambin existen y podemos definir en ese lenguaje. En Visual Basic 2005 se
siguen usando de la misma forma que en VB6, aunque seguramente siempre que hemos ledo
sobre el tema aparece la palabra delegado. Y es que, aunque VB2005 nos oculte, o facilite, el
trabajo con los eventos, stos siempre estn relacionados con los delegados. En esta leccin
veremos que son los delegados y que relacin tienen con los eventos, tambin veremos que
podemos tener mayor control sobre cmo se interceptan los eventos e incluso cmo y cuando
se asocian los eventos en la aplicacin cliente, aunque primero empezaremos viendo cmo
declarar y utilizar eventos en nuestros tipos de datos.
Eventos
En Visual Basic 2005 podemos usar los eventos de la misma forma que actualmente lo
hacemos en Visual Basic 6.0, al menos en lo que se refiere a la forma de declararlos en
nuestras clases y cmo "lanzarlos", ya que para interceptarlos en una aplicacin esa forma ha
cambiado un poco, pero como veremos, incluso puede ser ms fcil definir los mtodos o
procedimientos que utilizamos para interceptarlos.
End Sub
84
Handles Button1.Click
End Sub
Lo primero que podemos notar es que en Visual Basic 2005 utiliza dos argumentos, esto
siempre es as en todos los eventos producidos por los controles. El primero indica el control
que produce el evento, (en nuestro ejemplo sera una referencia al control Button1), y el
segundo normalmente contiene informacin sobre el evento que se produce, si el evento en
cuestin no proporciona informacin extra, como es el caso del evento Click, ese parmetro
ser del tipo EventArgs. Sin embargo en otros eventos, por ejemplo, los relacionados con el
ratn (mouse), el segundo argumento tendr informacin que nos puede resultar til, por
ejemplo para saber que botn se ha usado o cual es la posicin del cursor, en la figura 1.04.1
podemos ver las propiedades relacionadas con el evento MouseEventArgs:
End Sub
85
Nota:
En Visual Basic 2005 el nombre del procedimiento de evento no est relacionado
con el evento, a diferencia de Visual Basic 6.0, en el que si que hay una relacin
directa entre el evento a interceptar y el nombre del procedimiento.
Aunque por defecto, el nombre usado sera el equivalente al de VB6, en la nueva
versin puede tener cualquier nombre.
Tal como resaltamos en la nota anterior, en Visual Basic 2005, el nombre asociado a un
evento puede ser el que queramos, lo realmente importante es que indiquemos la instruccin
Handles seguida del evento que queremos interceptar.
86
eventos que ese control produce. Por tanto podemos seleccionar de esa lista de eventos el
que nos interese interceptar, tal como podemos ver en la figura 1.04.02
Figura 1.04.03 Ventana de propiedades con los eventos del control seleccionado
87
ByVal e As System.EventArgs) _
End Sub
88
usar en nuestro formulario, mientras que en esta nueva versin siempre tendremos acceso a
esa informacin. No vamos a entrar en ms detalles, simplemente mostraremos cmo se
declara el control Button1 para que exponga los eventos:
Friend WithEvents Button1 As System.Windows.Forms.Button
End Sub
Nota:
Usar WithEvents y Handles es la forma ms sencilla de declarar y usar una
variable que accede a una clase que produce eventos, pero no es la nica forma
que tenemos de hacerlo en Visual Basic 2005, tal como tendremos oportunidad
de comprobar.
Esto es todo lo que necesitamos hacer en Visual Basic 2005 para definir un evento, que, como
podemos comprobar, es exactamente igual que en VB6.
89
Esta es la forma ms sencilla de definir y lanzar eventos en Visual Basic 2005, que como
podemos comprobar es exactamente igual que en Visual Basic 6.0.
90
y el segundo es el procedimiento que usaremos cuando se produzca dicho evento. Este ltimo
parmetro tendremos que indicarlo mediante la instruccin AddressOf, que al igual que en
VB6 sirve para pasar una referencia a una funcin o procedimiento, y precisamente eso es lo
que queremos hacer: indicarle que procedimiento debe usar cuando se produzca el evento:
AddHandler unEmpleado.DatosCambiados, AddressOf unEmpleado_DatosCambiados
En este caso, el uso de AddressOf es una forma "fcil" que tiene Visual Basic 2005 de asociar
un procedimiento de evento con el evento. Aunque por el fondo, (y sin que nos enteremos),
realmente lo que estamos usando es un constructor a un delegado.
La ventaja de usar esta forma de asociar eventos con el procedimiento, es que podemos
hacerlo con variables que no estn declaradas con WithEvents, realmente esta sera la nica
forma de asociar un procedimiento de evento con una variable que no hemos declarado con
WithEvents.
Delegados
Como hemos comentado anteriormente, los eventos son acciones que una clase puede
producir cuando ocurre algo. De esta forma podemos notificar a las aplicaciones que hayan
decidido interceptar esos mensajes para que tomen las acciones que crean conveniente.
Visual Basic 2005 esconde al desarrollador prcticamente todo lo que ocurre cada vez que
decidimos interceptar un evento, nosotros solo vemos una pequea parte de todo el trabajo
que en realidad se produce, y el que no lo veamos no quiere decir que no est ocurriendo
nada. Tambin es cierto que no debe preocuparnos demasiado si no sabemos lo que est
pasando, pero si tenemos conciencia de que es lo que ocurre, puede que nos ayude a
comprender mejor todo lo relacionado con los eventos.
91
92
Es decir, el mtodo que intercepte este evento debe ser del tipo Sub y no recibir ningn
parmetro.
Si nuestro evento utiliza, por ejemplo, un parmetro de tipo String, la definicin del delegado
quedara de la siguiente forma:
Public Delegate Sub NombreCambiadoEventHandler(ByVal nuevoNombre As String)
93
Como vemos al definir el evento ya no tenemos que indicar si recibe o no algn parmetro, ya
que esa definicin la hemos hecho en el delegado.
Si nos decidimos a definir este evento de la forma "normal" de Visual Basic, lo haramos as:
Public Event NombreCambiado(ByVal nuevoNombre As String)
Como podemos comprobar, Visual Basic 2005 nos permite definir los eventos de dos formas
distintas: definiendo un delegado y un evento que sea del tipo de ese delegado o definiendo
el evento con los argumentos que debemos usar.
Declaremos como declaremos los eventos, los podemos seguir usando de la misma forma,
tanto para producirlo mediante RaiseEvent como para definir el mtodo que reciba ese
evento.
End Sub
Ahora vamos a declarar una variable para que acceda a ese mtodo.
Para ello debemos declararla con el mismo tipo del delegado:
Dim saludando As Saludo
La variable saludando es del mismo tipo que el delegado Saludo. La cuestin es cmo o que
asignamos a esta variable?
Primer intento:
Como hemos comentado, los delegados realmente son clases, por tanto podemos usar New
Saludo y, segn parece, deberamos pasarle un nombre como argumento. Algo as:
94
Pero esto no funciona, entre otras cosas, porque hemos comentado que un delegado contiene
(o puede contener) una referencia a un mtodo, y "Pepe" no es un mtodo ni una referencia
a un mtodo.
Segundo intento:
Por lgica y, sobre todo, por sentido comn, mxime cuando hemos declarado un mtodo con
la misma "firma" que el delegado, deberamos pensar que lo que debemos pasar a esa
variable es el mtodo, ya que un delegado puede contener una referencia a un mtodo.
saludando = New Saludo(mostrarSaludo)
Pues tampoco.
Para usar un delegado debemos indicarle la direccin de memoria de un mtodo, a eso se
refiere la definicin que vimos antes, una referencia a un mtodo no es ni ms ni menos que
la direccin de memoria de ese mtodo. Y en Visual Basic, desde la versin 5.0, tenemos una
instruccin para obtener la direccin de memoria de cualquier mtodo: AddressOf.
Por tanto, para indicarle al delegado dnde est ese mtodo tendremos que usar cualquiera
de estas dos formas:
saludando = New Saludo(AddressOf mostrarSaludo)
Ya que el compilador "sabe" que saludando es una variable de tipo delegado y lo que esa
variable puede contener es una referencia a un mtodo que tenga la misma firma que la
definicin del delegado, en nuestro caso, que sea de tipo Sub y reciba una cadena.
Si queremos, tambin podemos declarar la variable y asignarle directamente el mtodo al que
har referencia:
Dim saludando As New Saludo(AddressOf mostrarSaludo)
95
Con la diferencia de que la variable "saludando" no tiene porqu saber a qu mtodo est
llamando, y lo ms importante, no sabe dnde est definido ese mtodo, solo sabe que el
mtodo recibe un parmetro de tipo cadena y aparte de esa informacin, no tiene porqu
saber nada ms.
Realmente es complicado y, salvo que lo necesitemos para casos especiales, no ser muy
habitual que usemos los delegados de esta forma, aunque no est de ms saberlo, sobre todo
si de as comprendemos mejor cmo funcionan los eventos.
96
End AddHandler
End RemoveHandler
End RaiseEvent
End Event
Como podemos apreciar, debemos definir un delegado con la "firma" del mtodo a usar con el
evento.
Despus definimos el evento por medio de las instrucciones Custom Event, utilizando el
mismo formato que al definir un evento con un delegado.
Dentro de la definicin tenemos tres bloques, cada uno de los cuales realizar la accin que
ya hemos indicado en la lista numerada.
Nota:
Los eventos Custom Event solamente podemos definirlos e interceptarlos en el
mismo ensamblado.
97
ATRIBUTOS
Introduccin
Esta es la definicin que nos da la ayuda de Visual Basic sobre lo que es un atributo.
Los atributos son etiquetas descriptivas que proporcionan informacin adicional sobre
elementos de programacin como tipos, campos, mtodos y propiedades. Otras
aplicaciones, como el compilador de Visual Basic, pueden hacer referencia a la
informacin adicional en atributos para determinar cmo pueden utilizarse estos
elementos.
En esta leccin veremos algunos ejemplos de cmo usarlos en nuestras propias aplicaciones
y, aunque sea de forma general, cmo usar y aplicar algunos de los atributos definidos en el
propio .NET Framework, al menos los que ms directamente nos pueden interesar a los
desarrolladores de Visual Basic.
Atributos
Como hemos comentado en la introduccin, los atributos son etiquetas que podemos aplicar a
nuestro cdigo para que el compilador y, por extensin, el propio .NET Framework los pueda
usar para realizar ciertas tareas o para obtener informacin extra sobre nuestro cdigo.
De hecho en cualquier aplicacin que creemos con Visual Basic 2005 estaremos tratando con
atributos, aunque nosotros ni nos enteremos, ya que el propio compilador los utiliza para
generar los metadatos del ensamblado, es decir, la informacin sobre todo lo que contiene el
ejecutable o librera que hemos creado con Visual Basic 2005.
Por otra parte, el uso de los atributos nos sirve para ofrecer cierta funcionalidad extra a
nuestro cdigo, por ejemplo, cuando creamos nuestros propios controles, mediante atributos
podemos indicarle al diseador de formularios si debe mostrar ciertos miembros del control en
la ventana de propiedades, etc.
98
99
Esa informacin realmente est definida en un fichero del proyecto llamado AssembluInfo.vb,
el cual de forma predeterminada est oculto, si lo mostramos, veremos que esa informacin
la contiene en formato de atributos.
Parte del cdigo de ese fichero lo podemos ver en la figura 1.05.03:
100
Nota:
La palabra o instruccin Assembly: lo que indica es que el atributo tiene un
mbito de ensamblado.
101
Module MyResources
Atributos personalizados
Adems de los atributos que ya estn predefinidos en el propio .NET o Visual Basic, podemos
crear nuestros propios atributos, de forma que en tiempo de ejecucin podamos acceder a
ellos mediante las clases del espacio de nombres Reflection, aunque debido a que este tema
se sale un poco de la intencin de este curso, simplemente indicar que los atributos
personalizados son clases que se derivan de la clase System.Attribute y que podemos definir
las propiedades que creamos conveniente utilizar en ese atributo para indicar cierta
informacin a la que podemos acceder en tiempo de ejecucin.
En el siguiente cdigo tenemos la declaracin de una clase que se utilizar como atributo
personalizado, notamos que, por definicin las clases para usarlas como atributos deben
acabar con la palabra Attribute despus del nombre "real" de la clase, que como veremos en
el cdigo que utiliza ese atributo, esa "extensin" al nombre de la clase no se utiliza.
Veamos primero el cdigo del atributo personalizado:
<AttributeUsage(AttributeTargets.All)> _
Inherits System.Attribute
'
'
Get
Return _ModificadoPor
End Get
_ModificadoPor = value
102
End Set
End Property
'
Get
Return _Version
End Get
_Version = value
End Set
End Property
'
Get
Return _Fecha
End Get
_Fecha = value
End Set
End Property
End Class
103
<Autor(ModificadoPor:="Guillermo 'guille'", _
Version:="1.0.0.0", Fecha:="13/Abr/2005")> _
Nota:
Cuando utilizamos el atributo, en el constructor que de forma predeterminada
crea Visual Basic, los parmetros se indican por el orden alfabtico de las
propiedades, pero que nosotros podemos alterar usando directamente los
nombres de las propiedades, tal como podemos ver en el cdigo de ejemplo
anterior.
tipo = GetType(PruebaAtributos)
atributos = Attribute.GetCustomAttributes(tipo)
104
End If
Next
End Sub
COMClassAttribute
o
VBFixedStringAttribute
o
Este atributo se utiliza para crear cadenas de longitud fija en Visual Basic
2005. Habitualmente se aplica a campos o miembros de una estructura,
principalmente cuando queremos acceder al API de Windows o cuando
queremos usar esa estructura para guardar informacin en un fichero,
pero utilizando una cantidad fija de caracteres.
VBFixedArrayAttribute
o
105
Sub MostrarNombre()
Sub Mostrar()
End Interface
Si trabajamos con el IDE de Visual Basic, ese mensaje se mostrar al compilar o utilizar los
atributos marcados como obsoletos, tal como podemos apreciar en la figura 1.05.05:
106