VISUAL BASIC 2.

El nombre de los miembros de las enumeraciones
Tanto si indicamos o no el atributo Flags a una enumeración, la podemos usar de
esta forma:
Dim c As Colores = Colores.Azul Or Colores.Rojo
Es decir, podemos "sumar" los valores definidos en la enumeración. Antes de
explicar con detalle que beneficios nos puede traer el uso de este atributo, veamos
una característica de las enumeraciones.
Como hemos comentado, las enumeraciones son constantes con nombres, pero en
Visual Basic 2008 esta definición llega más lejos, de hecho, podemos saber "el
nombre" de un valor de una enumeración, para ello tendremos que usar el método
ToString, (el cual se usa para convertir en una cadena cualquier valor numérico).
Por ejemplo, si tenemos la siguiente asignación:
Dim s As String = Colores.Azul.ToString
La variable s contendrá la palabra "Azul" no el valor 4.
Esto es aplicable a cualquier tipo de enumeración, se haya o no usado el atributo
FlagsAttribute.
Una vez aclarado este comportamiento de las enumeraciones en Visual Basic
2008, veamos que es lo que ocurre cuando sumamos valores de enumeraciones a
las que hemos aplicado el atributo Flags y a las que no se lo hemos aplicado.
Empecemos por este último caso.
Si tenemos este código:
Enum Colores As Byte
Rojo = 1
Verde = 2
Azul = 4
End Enum
Dim c As Colores = Colores.Azul Or Colores.Rojo
Dim s As String = c.ToString
El contenido de la variable s será "5", es decir, la representación numérica del
valor contenido: 4 + 1, ya que el valor de la constante Azul es 4 y el de la
constante Rojo es 1.
Pero si ese mismo código lo usamos de esta forma (aplicando el atributo Flags a la
enumeración):
<Flags()> _
Enum Colores As Byte
Rojo = 1
Verde = 2
Azul = 4
End Enum
Dim c As Colores = Colores.Azul Or Colores.Rojo
Dim s As String = c.ToString
El contenido de la variable s será: "Rojo, Azul", es decir, se asignan los nombres
de los miembros de la enumeración que intervienen en ese valor, no el valor
"interno".
Los valores de una enumeración no son simples números
Como hemos comentado, los miembros de las enumeraciones realmente son
valores de un tipo de datos entero (en cualquiera de sus variedades) tal como
podemos comprobar en la figura 2.7:
Figura 2.7. Los tipos subyacentes posibles de una enumeración
Por tanto, podemos pensar que podemos usar cualquier valor para asignar a una
variable declarada como una enumeración, al menos si ese valor está dentro del
rango adecuado.
En Visual Basic 2008 esto no es posible, al menos si lo hacemos de forma "directa"
y con Option Strict conectado, ya que recibiremos un error indicándonos que no
podemos convertir, por ejemplo, un valor entero en un valor del tipo de la
enumeración. En la figura 2.8 podemos ver ese error al intentar asignar el valor 3
a una variable del tipo Colores (definida con el tipo predeterminado Integer).
Figura 2.8. Error al asignar un valor "normal" a una variable del tipo
Colores
El error nos indica que no podemos realizar esa asignación, pero el entorno
integrado de Visual Studio 2008 también nos ofrece alternativas para que ese
error no se produzca, esa ayuda se obtiene presionando en el signo de admiración
que tenemos justo donde está el cursor del mouse, pero no s olo nos dice cómo
corregirlo, sino que también nos da la posibilidad de que el propio IDE se encargue
de corregirlo, tal como podemos apreciar en la figura 2.9.
Figura 2.9. Opciones de corrección de errores
Lo único que tendríamos que hacer es presionar en la sugerencia de corrección,
que en este caso es la única que hay, pero en otros casos pueden ser varias las
opciones y tendríamos que elegir la que creamos adecuada.
El código final (una vez corregido) quedaría de la siguiente forma:
Dim c As Colores = CType(3, Colores)
CType es una de las formas que nos ofrece Visual Basic 2008 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 aplicación, é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 podríamos darlo por bueno, ya que es
la suma de 1 y 2 (Rojo y Verde), pero ¿que pasaría si el valor asignado es, por
ejemplo, 15? En teoría no deberíamos permitirlo.
Estas validaciones podemos hacerlas de dos formas:
1- Con la clásica solución de comprobar el valor indicado con todos los valores
posibles.
2- Usando funciones específicas del tipo Enum. Aunque en este último caso, solo
podremos comprobar los valores definidos en la enumeración.
En el siguiente ejemplo podemos hacer esa comprobación.
Sub mostrarColor(ByVal c As Colores)
' comprobar si el valor indicado es correcto
' si no está¡ definido, usar el valor Azul
If [Enum].IsDefined(GetType(Colores), c) = False Then
c = Colores.Azul
End If
Console.WriteLine("El color es {0}", c)
End Sub
Este código 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 función IsDefined sólo comprueba los valores que se han definido
en la enumeración, no las posibles combinaciones que podemos
conseguir sumando cada uno de sus miembros, incluso aunque
hayamos usado el atributo FlagsAttribute.
Ver vídeo 1 de esta lección (Enumeraciones 1) - video en Visual
Studio 2005 válido para Visual Studio 2008
Ver vídeo 2 de esta lección (Enumeraciones 2) - video en Visual
Studio 2005 válido para Visual Studio 2008
Ver vídeo 3 de esta lección (Enumeraciones 3) - video en Visual
Studio 2005 válido para Visual Studio 2008
Ver vídeo 4 de esta lección (Enumeraciones 4) - video en Visual
Studio 2005 válido para Visual Studio 2008
Arrays (matrices)
Los arrays (o matrices) nos permitirán agrupar valores que de alguna forma
queremos que estén relacionados entre si.
Nota:
Esta es la definición usada en la documentación de Visual Studio
sobre qué es una matriz:
"Una matriz es una estructura de datos que contiene una serie de
variables denominadas elementos de la matriz."
Aclaramos este punto, porque la traducción en castellano de Array
puede variar dependiendo del país, pero aquí utilizaremos la usada a
lo largo de la documentación de Visual Studio.
Declarar arrays
En C# los arrays se definen indicando un par de corchetes en el tipo de datos.
En Visual Basic 2008 la declaración de un array la haremos usando un par de
paréntesis en el nombre de la variable o del tipo, en el siguiente ejemplo
declaramos un array de tipo String llamado nombres:
Dim nombres() As String
Dim nombres As String()
Estas dos formas son equivalentes.
También podemos indicar el número de elementos que contendrá el array:
Dim nombres(10) As String
Pero solo podemos hacerlo en el nombre, si esa cantidad de elementos lo
indicamos en el tipo, recibiremos un error indicándonos que "los límites de la
matriz no pueden aparecer en los especificadores del tipo".
Al declarar un array indicando el número de elementos, como es el caso anterior,
lo que estamos definiendo es un array de 11 elementos: desde cero hasta 10, ya
que en Visual Basic 2008, al igual que en el resto de lenguajes de .NET, todos los
arrays deben tener como índice inferior el valor cero.
Para que quede claro que el límite inferior debe ser cero, en Visual Basic 2008
podemos usar la instrucción 0 To para indicar el valor máximo del índice superior,
ya que, tal como podemos comprobar si vemos 0 To 10, quedará claro que
nuestra intención es declarar un array con 11 elementos, o al menos nue stro
código resultará más legible:
Dim nombres(0 To 10) As String
Declarar e inicializar un array
En Visual Basic 2008 también podemos inicializar un array al declararlo, para ello
debemos poner los valores a asignar dentro de un para de llaves, tal como v emos
en el siguiente ejemplo:
Dim nombres() As String = {"Pepe", "Juan", "Luisa"}
Con el código anterior estamos creando un array de tipo String con tres valores
cuyos índices van de cero a dos.
En este caso, cuando iniciamos el array al declararlo, no deb emos indicar el
número de elementos que tendrá ese array, ya que ese valor lo averiguará el
compilador cuando haga la asignación. Tampoco es válido indicar el número de
elementos que queremos que tenga y solo asignarle unos cuantos menos (o más),
ya que se producirá un error en tiempo de compilación.
Si el array es bidimensional (o con más dimensiones), también podemos
inicializarlos al declararlo, pero en este caso debemos usar doble juego de llaves:
Dim nombres(,) As String = {{"Juan", "Pepe"}, {"Ana", "Eva"}}
En este código tendríamos un array bidimensional con los siguientes valores:
nombres(0,0)= Juan
nombres(0,1)= Pepe
nombres(1,0)= Ana
nombres(1,1)= Eva
Como podemos ver en la declaración anterior, si definimos arrays con más de una
dimensión, debemos indicarlas usando una coma para separar cada dimensión, o
lo que es más fácil de recordar: usando una coma menos del número de
dimensiones que tendrá el array. En los valores a asignar, usaremos las llaves
encerradas en otras llaves, según el número de dimensiones.
Aunque, la verdad, es que hay algunas veces hay que hacer un gran esfuerzo
mental para asociar los elementos con los índices que tendrán en el array, por
tanto, algunas veces puede que resulte más legible si indentamos o agrupamos
esas asignaciones, tal como vemos en el siguiente código:
Dim nomTri(,,) As String = _
{ _
{{"Juan", "Pepe"}, {"Luisa", "Eva"}}, _
{{"A", "B"}, {"C", "D"}} _
}
Console.WriteLine(nomTri(0, 0, 0)) ' Juan
Console.WriteLine(nomTri(0, 0, 1)) ' Pepe
Console.WriteLine(nomTri(0, 1, 0)) ' Luisa
Console.WriteLine(nomTri(0, 1, 1)) ' Eva
Console.WriteLine(nomTri(1, 0, 0)) ' A
Console.WriteLine(nomTri(1, 0, 1)) ' B
Console.WriteLine(nomTri(1, 1, 0)) ' C
Console.WriteLine(nomTri(1, 1, 1)) ' D
Tal como podemos comprobar, asi es más legible. Por suerte tenemos el carácter
del guión bajo para continuar líneas de código.
Cambiar el tamaño de un array
Para cambiar el tamaño de un array, usaremos la instrucción ReDim, esta
instrucción solo la podemos usar para cambiar el tamaño de un array previamente
declarado, no para declarar un array, ya que siempre hay que declarar
previamente los arrays antes de cambiarles el tamaño.
Dim nombres() As String
...
ReDim nombres(3)
nombres(0) = "Juan"
nombres(1) = "Pepe"
La mayor utilidad de esta instrucción, es que podemos cambiar el tamaño de un
array y mantener los valores que tuviera anteriormente, para lograrlo debemos
usar ReDim Preserve.
ReDim Preserve nombres(3)
nombres(2) = "Ana"
nombres(3) = "Eva"
En este ejemplo, los valores que ya tuviera el array nombres, se seguirían
manteniendo, y se asignarían los nuevos.
Si bien tanto ReDim como ReDim Preserve se pueden usar en arrays de cualquier
número de dimensiones, en los arrays de más de una dimensión solamente
podemos cambiar el tamaño de la última dimensión.
Eliminar el contenido de un array
Una vez que hemos declarado un array y le hemos asignado valores, es posible
que nos interese eliminar esos valores de la memoria, para lograrlo, podemos
hacerlo de tres formas:
1. Redimensionando el array indicando que tiene cero elementos, aunque en el
mejor de los casos, si no estamos trabajando con arrays de más de una
dimensión, tendríamos un array de un elemento, ya que, como hemos
comentado anteriormente, los arrays de .NET el índice inferior es cero.
2. Usar la instrucción Erase. La instrucción Erase elimina totalmente el array de
la memoria.
3. Asignar un valor Nothing al array. Esto funciona en Visual Basic 2008 porque
los arrays realmente son tipos por referencia.
Los arrays son tipos por referencia
Como acabamos de ver, en Visual Basic 2008 los arrays son tipos por referencia, y
tal como comentamos anteriormente, los tipos por referencia realmente lo que
contienen son una referencia a los datos reales no los datos propiame nte dichos.
¿Cual es el problema?
Veámoslo con un ejemplo y así lo tendremos más claro.
Dim nombres() As String = {"Juan", "Pepe", "Ana", "Eva"}
Dim otros() As String
otros = nombres
nombres(0) = "Antonio"
En este ejemplo definimos el array nombres y le asignamos cuatro valores. A
continuación definimos otro array llamado otros y le asignamos lo que tiene
nombres. Por último asignamos un nuevo valor al elemento cero del array
nombres.
Si mostramos el contenido de ambos arrays nos daremos cuenta de que realmente
solo existe una copia de los datos en la memoria, y tanto nombres(0) como
otros(0) contienen el nombre "Antonio".
¿Qué ha ocurrido?
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 fácil de hacer si usamos el método
CopyTo. Éste método 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 código 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"}
Dim otros() As String
ReDim otros(nombres.Length)
nombres.CopyTo(otros, 0)
nombres(0) = "Antonio"
Además del método 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 número de elementos de un array, (realmente el índice
superior), podemos usar la función UBound.
También podemos usar la función LBound, (que sirve para averiguar el índice
inferior de un array), aunque no tiene ningún sentido en Visual Basic 2008, ya
que, como hemos comentado, 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
2008 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 próxima lección, en la que también tendremos la oportunidad de
profundizar un poco más en los tipos por referencia y en como podemos definir
nuestros propios tipos de datos, tanto por referencia como por valor.
Ver vídeo 1 de esta lección (Arrays Parte 1) - video en Visual Studio
2005 válido para Visual Studio 2008
Ver vídeo 2 de esta lección (Arrays Parte 2) - video en Visual Studio
2005 válido para Visual Studio 2008
Ver vídeo 3 de esta lección (Arrays Parte 3) - video en Visual Studio
2005 válido para Visual Studio 2008
Introducción
En la lección anterior vimos los tipos de datos predefinidos en .NET Framework, en
esta lección veremos cómo podemos crear nuestros propios tipos de datos, tanto
por valor como por referencia.
También tendremos ocasión de ver los distintos niveles de accesibilidad que
podemos aplicar a los tipos, así como a los distintos miembros d e 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. También veremos temas relacionados con la programación
orientada a objetos (POO) en general y de forma particular los que atañen a las
interfaces.
Clases y estructuras
· Clases: Tipos por referencia definidos por el usuario
o Las clases: El corazón de .NET Framework
o La herencia: Característica principal de la Programación Orientada a
Objetos
o Encapsulación y Polimorfismo
o Object: La clase base de todas las clases de .NET
· Definir una clase
o Una clase especial: Module
o Los miembros de una clase
o Características de los métodos y propiedades
§ Accesibilidad, ámbito y miembros compartidos
§ Parámetros y parámetros opcionales
§ Array de parámetros opcionales (ParamArray)
§ Sobrecarga de métodos y propiedades
§ Parámetros por valor y parámetros por referencia
· Instanciar: Crear un objeto en la memoria
o Declarar primero la variable y después instanciarla
o Declarar y asignar en un solo paso
o El constructor: El punto de inicio de una clase
o Constructores parametrizados
o Cuando Visual Basic 2008 no crea un constructor automáticamente
o El destructor: El punto final de la vida de una clase
o Inicialización directa de objetos
· Estructuras: Tipos por valor definidos por el usuario
o Definir una estructura
o Constructores de las estructuras
o Destructores de las estructuras
o Los miembros de una estructura
o Cómo usar las estructuras
· Accesibilidad y ámbito
o Ámbito
§ Ámbito de bloque
§ Ámbito de procedimiento
§ Ámbito de módulo
§ Ámbito de espacio de nombres
o La palabra clave Global
o Accesibilidad
§ Accesibilidad de las variables en los procedimientos
o Las accesibilidades predeterminadas
o Anidación de tipos
§ Los tipos anidables
§ El nombre completo de un tipo
§ Importación de espacios de nombres
§ Alias de espacios de nombres
· Propiedades
o Definir una propiedad
o Propiedades de solo lectura
o Propiedades de solo escritura
o Diferente accesibilidad para los bloques Get y Set
o Propiedades predeterminadas
§ Sobrecarga de propiedades predeterminadas
· Interfaces
o ¿Qué es una interfaz?
o ¿Qué contiene una interfaz?
o Una interfaz es un contrato
o Las interfaces y el polimorfismo
o Usar una interfaz en una clase
o Acceder a los miembros implementados
o Saber si un objeto implementa una interfaz
o Implementación de múltiples interfaces
o Múltiple implementación de un mismo miembro
o ¿Dónde podemos implementar las interfaces?
o Un ejemplo práctico usando una interfaz de .NET
Clases: Tipos por referencia definidos por el usuario
Tal como vimos en la lección anterior, los tipos de datos se dividen en dos grupos:
tipos por valor y tipos por referencia. Los tipos por referencia realmente son
clases, de la cuales debemos crear una instancia para poder usarlas, esa instancia
o copia, se crea siempre en la memoria lejana (heap) y las variables lo único que
contienen es una referencia a la dirección de memoria en l a que el CLR (Common
Language Runtime, motor en tiempo de ejecución de .NET), ha almacenado el
objeto recién creado.
En .NET Framework todo es de una forma u otra una clase, por tanto Visual Basic
2008 también depende de la creación de clases para su funci onamiento, ya que
todo el código que escribamos debemos hacerlo dentro de una clase.
Antes de entrar en detalles sintácticos, veamos la importancia que tienen las
clases en .NET Framework y como repercuten en las que podamos definir nosotros
usando Visual Basic 2008.
Las clases: el corazón de .NET Framework
Prácticamente todo lo que podemos hacer en .NET Framework lo hacemos
mediante clases. La librería de clases de .NET Framework es precisamente el
corazón del propio .NET, en esa librería de clases está to do lo que podemos hacer
dentro de este marco de programación; para prácticamente cualquier tarea que
queramos realizar existen clases, y si no existen, las podemos definir nosotros
mismos, bien ampliando la funcionalidad de alguna clase existente mediante la
herencia, bien implementando algún tipo de funcionalidad previamente definida o
simplemente creándolas desde cero.
La herencia: Característica principal de la Programación Orientada a
Objetos
El concepto de Programación Orientada a Objetos (POO) es algo intrínsico al
propio .NET Framework, por tanto es una característica que todos los lenguajes
basados en este "marco de trabajo" tienen de forma predeterminada, entre ellos el
Visual Basic 2008. De las características principales de la POO tenemos que
destacar la herencia, que en breve podemos definir como una característica que
nos permite ampliar la funcionalidad de una clase existente sin perder la que ya
tuviera previamente. Gracias a la herencia, podemos crear una nueva clase que se
derive de otra, esta nueva clase puede cambiar el comportamiento de la clase
base y/o ampliarlo, de esta forma podemos adaptar la clase, llamémosla, original
para adaptarla a nuestras necesidades.
El tipo de herencia que .NET Framework soporta es la herencia simple, es decir ,
solo podemos usar una clase como base de la nueva, si bien, como veremos más
adelante, podemos agregar múltiple 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 más detalle.
Encapsulación y Polimorfismo
La encapsulación y el polimorfismo son otras dos características de la
programación orientada a objetos.
La encapsulación nos permite abstraer la forma que tiene de actuar una clase
sobre los datos que contiene o manipula, para poder lograrlo se exponen como
parte de la clase los métodos y propiedades necesarios para que podamos manejar
esos datos sin tener que preocuparnos cómo se realiza dicha manipulación.
El polimorfismo es una característica que nos permite realizar ciertas acciones o
acceder a la información de los datos contenidos en una clase de forma semi -
anónima, al menos en el sentido de que no tenemos porqué saber sobre que tipo
objeto realizamos la acción, ya que lo único que nos debe preocupar es que
podemos hacerlo, por la sencilla razón de que estamos usando ciertos mecanismos
que siguen unas normas que están adoptadas por la clase.
El ejemplo clásico del polimorfismo es que si tengo un objeto que "sabe" cómo
morder, da igual que lo aplique a un ratón o a un dinosaurio, siempre y cuando
esas dos "clases" expongan un método que pueda realizar esa acción... y como
decía la documentación de Visual Basic 5.0, siempre será preferible que nos
muerda un ratón antes que un dinosaurio.
Object: La clase base de todas las clases de .NET
Todas las clases de .NET se derivan de la clase Object, es decir, lo indiquemos o
no, cualquier clase que definamos tendrá el comportamiento heredado de esa
clase. El uso de la clase Object como base del resto de las clases de .NET es la
única excepción a la herencia simple soportada por .NET, ya que de forma
implícita, todas las clases de .NET se derivan de la clase Object
independientemente de que estén derivadas de cualquier otra.
Esta característica nos asegura que siempre podremos usar un objeto del tipo
Object para acceder a cualquier clase de .NET, aunque no debemos abrumarnos
todavía, ya que en el texto que sigue veremos con más detalle que significado
tiene esta afirmación.
De los miembros que tiene la clase Object debemos resaltar el método ToString, el
cual ya lo vimos en la lección anterior cuando queríamos convertir un tipo
primitivo en una cadena. Este método está pensado para devolver una
representación en formato cadena de un objeto. El valor que obtengamos al usar
este método dependerá de cómo esté definido en cada clase y por defecto lo que
devuelve es el nombre completo de la clase, si bien en la mayoría de los casos el
valor que obtendremos al usar este método debería ser más intuitivo, por ejemplo
los tipos de datos primitivos tienen definido este método para devuelva el valor
que contienen, de igual forma, nuestras clases también deberían devolver un valor
adecuado al contenido almacenado. De cómo hacerlo, nos ocuparemos en breve.
Nota:
Todos los tipos de datos de .NET, ya sean por valor o por referencia
siempre están derivados de la clase Object, por tanto podremos
llamar a cualquiera de los métodos que están 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 objeto por referencia (boxing) y cuando
hemos dejado de usarla y queremos volver a asignar el dato a la
variable por valor, tiene que volver a hacer la conversión inversa
(unboxing).
Ver vídeo de esta lección (Clases 1) - video en Visual Studio 2005
válido para Visual Studio 2008
Definir una clase
En Visual Basic 2008, todo el código que queramos escribir, lo tendremos que
hacer en un fichero con la extensión .vb, dentro de ese fichero es donde
escribiremos nuestro código, el cual, tal como dijimos anteriormente siempre
estará incluido dentro de una clase, aunque un fichero de código de VB puede
contener una o más clases, es decir, no está limitado a una clase por fichero.
En Visual Basic 2008 las clases se definen usando la palabra clave Class seguida
del nombre de la clase, esa definición acaba indicándolo con End Class.
En el siguiente ejemplo definimos una clase llamada Cliente que tiene dos campos
públicos.
Class Cliente
Public Nombre As String
Public Apellidos As String
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 públicos,
aunque también podríamos haber definido cualquiera de los miembros permitidos
en las clases.
Una clase especial: Module
En Visual Basic 2008 también podemos definir una clase especial llamada Module,
este tipo de clase, como veremos, tiene un tratamiento especial.
La definición se hace usando la instrucción Module seguida del nombre a usar y
acaba con End Module.
Cualquier miembro definido en un Module siempre estará accesible en todo el
proyecto y para usarlos no tendremos que crear ningún objeto en memoria.
Las clases definidas con la palabra clave Module realmente equivalen a las clases
en las que todos los miembros están compartidos y por tanto siempre disponibles
a toda la aplicación.
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 da tos que el
IDE de Visual Basic 2008 usará al crear aplicaciones del tipo consola, ya que ese
será el tipo de proyecto que crearemos para practicar con el código mostrado en
este primer módulo.
Los miembros de una clase
Una clase puede contener cualquiera de estos elementos (miembros):
· Enumeraciones
· Campos
· Métodos (funciones o procedimientos)
· Propiedades
· Eventos
Las enumeraciones, como vimos en la lección anterior, podemos usarlas para
definir valores constantes relacionados, por ejemplo para indicar lo s valores
posibles de cualquier "característica" de la clase.
Los campos son variables usadas para mantener los datos que la clase
manipulará.
Los métodos son las acciones que la clase puede realizar, normalmente esas
acciones serán sobre los datos que contiene. Dependiendo de que el método
devuelva o no un valor, podemos usar métodos de tipo Function o de tipo Sub
respectivamente.
Las propiedades son las "características" de las clases y la forma de acceder
"públicamente" a los datos que contiene. Por ejemplo, podemos considerar que el
nombre y los apellidos de un cliente son dos características del cliente.
Los eventos son mensajes que la clase puede enviar para informar que algo está
ocurriendo en la clase.
Características de los métodos y propiedades
Accesibilidad, ámbito y miembros compartidos
Aunque estos temas los veremos en breve con más detalle, para poder
comprender mejor las características de los miembros de una clase (o cualquier
tipo que definamos), daremos un pequeño adelanto sobre estas caract erísticas que
podemos aplicar a los elementos que definamos.
Accesibilidad y ámbito son dos conceptos que están estrechamente relacionados.
Aunque en la práctica tienen el mismo significado, ya que lo que representan es la
"cobertura" o alcance que tienen los miembros de las clases e incluso de las
mismas clases que definamos.
Si bien cada uno de ellos tienen su propia "semántica", tal como podemos ver a
continuación:
Ámbito
Es el alcance que la definición de un miembro o tipo puede tener. Es decir, cómo
podemos acceder a ese elemento y desde dónde podemos accederlo.
El ámbito de un elemento de código está restringido por el "sitio" en el que lo
hemos declarado. Estos sitios pueden ser:
· Ámbito de bloque: Disponible únicamente en el bloque de código en el que
se ha declarado.
· Ámbito de procedimiento: Disponible únicamente dentro del
procedimiento en el que se ha declarado.
· Ámbito de módulo: Disponible en todo el código del módulo, la clase o la
estructura donde se ha declarado.
· Ámbito de espacio de nombres: Disponible en todo el código del espacio
de nombres.
Accesibilidad
A los distintos elementos de nuestro código (ya sean clases o miembros de las
clases) podemos darle diferentes tipos de accesibilidad. Estos tipos de "acceso"
dependerán del ámbito que queramos que tengan, es decir, desde dónde
podremos accederlos.
Los modificadores de accesibilidad son:
· Public: Acceso no restringido.
· Protected: Acceso limitado a la clase contenedora o a los tipos derivados de
esta clase.
· Friend: Acceso limitado al proyecto actual.
· Protected Friend: Acceso limitado al proyecto actual o a los tipos derivados
de la clase contenedora.
· Private: Acceso limitado al tipo contenedor.
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 declarar una variable con Dim, el ámbito que le estamos aplicando
por regla general, es privado, pero como veremos, en Visual Basic
2008 el ámbito puede ser diferente a privado dependiendo del tipo en
el que declaremos esa variable.
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 están 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 aplicación.
Del ámbito, la accesibilidad y los miembros compartidos nos ocuparemos c on más
detalle en una lección posterior, donde veremos ciertas peculiaridades, como
puede ser la limitación del ámbito de un miembro que aparentemente tiene una
accesibilidad no restringida.
Parámetros específicos y parámetros opcionales
En Visual Basic 2008, tanto los miembros de una clase, (funciones y métodos
Sub), como las propiedades pueden recibir parámetros. Esos parámetros pueden
estar explícitamente declarados, de forma que podamos indicar cuantos
argumentos tendremos que pasar al método, también p odemos declarar
parámetros opcionales, que son parámetros que no hace falta indicar al llamar a la
función o propiedad, y que siempre tendrán un valor predeterminado, el cual se
usará en caso de que no lo indiquemos.
Además de los parámetros específicos y opcionales, podemos usar un array de
parámetros opcionales, en los que se puede indicar un número variable de
argumentos al llamar a la función que los define, esto lo veremos en la siguiente
sección.
Nota: Sobre parámetros y argumentos
Para clarificar las cosas, queremos decir que los parámetros son los
definidos en la función, mientras que los argumentos son los
"parámetros" que pasamos a esa función cuando la utilizamos desde
nuestro código.
Con los parámetros opcionales lo que conseguimos es permitir qu e el usuario no
tenga que introducir todos los parámetros, sino solo los que realmente necesite,
del resto, (los no especificados), se usará el valor predeterminado que hayamos
indicado, porque una de las "restricciones" de este tipo de parámetros, es que
siempre debemos indicar también el valor por defecto que debemos usar en caso
de que no se especifique.
Veamos unos ejemplo para aclarar nuestras ideas:
Function Suma(n1 As Integer, Optional n2 As Integer = 15) As
Integer
Suma = n1 + n2
End Function
En este primer ejemplo, el primer parámetro es obligatorio (siempre debemos
indicarlo) y el segundo es opcional, si no se indica al llamar a esta función, se
usará el valor 15 que es el predeterminado.
Para llamar a esta función, lo podemos hacer de estas tres formas:
' 1- indicando los dos parámetros (el resultado será 4= 1 + 3)
t = Suma(1, 3)
' 2- Indicando solamente el primer parámetro (el resultado será
16= 1 + 15)
t = Suma(1)
' 3- Indicando los dos parámetros, pero en el opcional usamos el
nombre
t = Suma(1, n2:= 9)
El tercer ejemplo solamente tiene utilidad si hay más de un parámetro opcional.
Nota:
Los parámetros opcionales deben aparecer en la lista de parámetros
del método, después de los "obligatorios"
Nota:
En el caso hipotético y no recomendable de que no estemos usando
Option Strict On, tanto los parámetros normales como los opcionales
los podemos indicar sin el tipo de datos, pero si en alguno de ellos

especificamos el tipo, debemos hacerlo en todos.