Professional Documents
Culture Documents
http://www.cuatrovientos.org
Autoras: Mara Martn y Susana Moreno
Emails: maria_martin@cuatrovientos.org
susana_moreno@cuatrovientos.org
Mdulo: Programacin
VB.Net (ndice)
Pg. 3
Constantes.......................................................................................................................... 50
Alcance de las constantes definidas por el usuario ....................................................... 51
Operadores ........................................................................................................................ 51
Diferencia entre And y AndAlso as como entre Or y OrElse ....................................... 52
Prioridad de operadores ............................................................................................... 53
Uso de parntesis para alterar la prioridad de operadores ............................................. 53
Comentarios ....................................................................................................................... 54
Instrucciones en VB.Net .................................................................................................... 54
Asignacin (=) y operadores abreviados +=, *=, -=. /=, &= .............................................. 55
Instruccin Condicional simple y mltiple: If ................................................................... 55
Condicional mltiple: Select Case .................................................................................... 56
Usando la Select Case para determinar los botones chequeados ................................... 58
Bucles While..Wend y Do..Loop ....................................................................................... 58
Bucle For ........................................................................................................................ 59
Declaracin de variables a nivel de bloque ....................................................................... 60
Manejo de excepciones: Bloque Try..Catch ...................................................................... 61
Bloque Try....................................................................................................................... 61
Bloque Catch ................................................................................................................... 61
Varias capturas de errores en un mismo bloque Try/Catch ................................................ 62
Bloque Finally ................................................................................................................. 62
Lanzar una excepcin por cdigo...................................................................................... 63
VB.Net (ndice)
Pg. 4
String.Compare ................................................................................................................ 77
Longitud y caracteres de una cadena ................................................................................ 78
Ver si una cadena est includa en otra: Contains, IndexOf, StartsWith y EndWith ........... 78
Manipular cadenas: SubString, Remove, Replace, Insert, Trim, ToUpper y ToLower ....... 79
Creacin de nmeros aleatorios ........................................................................................ 79
VB.Net (ndice)
Pg. 5
VB.Net (ndice)
Pg. 6
VB.Net (ndice)
Pg. 7
VB.Net (ndice)
Pg. 8
.Net Framework
.NET Framework constituye la plataforma y elemento principal sobre el que se asienta
Microsoft .NET. De cara al programador o programadora, es la pieza fundamental de todo este
nuevo modelo de trabajo, ya que proporciona las herramientas y servicios que necesitar en su
labor habitual de desarrollo.
.NET Framework permite el desarrollo de aplicaciones a travs del uso de un conjunto de
herramientas y servicios que proporciona, y que pueden agruparse en tres bloques principales: el
Entorno de Ejecucin Comn o Common Language Runtime (CLR a partir de ahora); la
jerarqua de clases bsicas de la plataforma o .NET Framework Base Classes; y el motor de
generacin de interfaz de usuari@, que permite crear interfaces para la web o para el tradicional
entorno Windows, as como servicios para ambos entornos operativos.
Pg. 9
Cuando creamos una nueva aplicacin Windows en VB.Net .NET, se nos proporciona un
cdigo inicial que incluye el espacio de nombres System.Windows.Forms y la clase Form.
Con esta clase, podemos crear fcilmente ventanas, botones, mens, barras de herramientas y
otros elementos de pantalla. Cuando compilamos la aplicacin, el cdigo se traduce al lenguaje
comn del entorno de ejecucin, Microsoft Intermediate Language (MSIL). Una vez la
aplicacin se ha compilado, el entorno de ejecucin gestiona su ejecucin.
El entorno de ejecucin incluye una caracterstica denominada compilacin just-in-time
(JIT), que traduce cdigo MSIL al lenguaje mquina del sistema en el que la aplicacin se
ejecutar. Cuando un dispositivo cliente con la plataforma .NET lanza la aplicacin en VB.Net
.NET, se ejecuta en el lenguaje mquina del sistema cliente y puede integrarse totalmente e
interactuar con otras aplicaciones y servicios basados en .NET independientemente del lenguaje
en el que hayan sido desarrollados.
Pg. 10
Visual Basic.Net
Visual Basic.Net (VB.Net a partir de ahora) es uno de los diferentes lenguajes que componen
VS.Net.
VB.Net ofrece importantes innovaciones del lenguaje respecto a versiones anteriores de
Visual Basic .NET soporta herencia, constructores, polimorfismo, sobrecarga, excepciones
estructuradas, estricta verificacin de tipos, free threading, y muchas otras caractersticas que
iremos viendo a lo largo del curso.
En nuestro caso utilizaremos este lenguaje para crear aplicaciones de escritorio, basadas en
la Programacin Orientada a Objetos u POO a partir de ahora (Object Oriented Programming
con las siglas OOP).
Las aplicaciones de escritorio son aquellas basadas en ventanas y controles comunes de
Windows que se ejecutan en local.
Lo primero que vamos a hacer es crear un nuevo proyecto. Un proyecto contiene todos
los archivos necesarios para la aplicacin y almacena informacin sobre la misma. Incluso,
una aplicacin puede contener ms de un proyecto, por ejemplo, un proyecto de aplicacin
para Windows y uno o varios proyectos de biblioteca de clases. La aplicacin se denomina
solucin, y se guarda en un fichero de extensin sln.
Para realizar lo que estamos diciendo, elige Nuevo proyecto y te aparecer una nueva
ventana del tipo:
Pg. 11
Como puedes observar Visual Studio .NET ofrece varias plantillas de aplicaciones para
soportar el desarrollo de diferentes tipos de aplicaciones y componentes. Antes de iniciar un
nuevo proyecto, debemos escoger el tipo de plantilla que deseamos utilizar.
En nuestro caso escogeremos la primera opcin: Aplicacin de Windows Forms dentro de la
plantilla de VB.Net.
Sugerencia: Observa en la parte de abajo, que en la caja de texto etiquetada con Nombre
pone WindowsApplication1, que ser el adjudicado a nuestra aplicacin. Lo mejor ser poner
un nombre identificativo que nos indique lo que realiza el programa, como puede apreciarse en
las siguientes figuras:
Ahora haz clic en el botn Aceptar. Te aparece una ventana parecida a la que te muestro a
continuacin? Es posible que en la parte izquierda o derecha tengas otra presentacin,
mostrando el Cuadro de herramientas (fjate a la izquierda de la siguiente figura) o no
apareciendo tan visible el Explorador de soluciones o la ventana de Propiedades. Verlo o no
depender de cmo est configurado el entorno de desarrollo. Hacerlo ser fcilmente
modificable. Sitate sobre la que est minimizada (en la imagen el Cuadro de herramientas) y
vers que se expande al lado. Si por el contrario deseas minimizarla (como en el caso del
Explorador de soluciones y Propiedades) solo debers situarte sobre el icono semejante a una
chincheta que tienes en el marco de la ventana. Hazlo y vers que pasa.
Pg. 12
Fichas ocultas
Fichas visibles
Sugerencia: Al igual que antes para el proyecto, vamos a cambiar el nombre del
formulario. Para eso te posicionas con el botn secundario del ratn sobre el icono del
formulario y tras elegir Cambiar nombre escribes el que puedes ver a continuacin.
Los comandos del men principal funcionan igual que en todas las aplicaciones basadas en
Windows, y podemos acceder a ellos utilizando el teclado o el ratn.
La barra de herramientas estndar proporciona botones que sirven como accesos directos a la
mayora de los comandos ms habituales, como Abrir, Guardar, Inicio, Aadir nuevo
elemento, Ir hacia atrs e Ir hacia adelante. Tambin contiene botones que abren el
Explorador de soluciones, la ventana de Propiedades, el Cuadro de herramientas, y otros
elementos importantes del entorno de desarrollo. Puede ser que tambin tengas la de
Depuracin. Esta proporciona accesos directos a las funcionalidades de depuracin, como ir
paso a paso en el cdigo y establecer puntos de interrupcin.
Pg. 13
Cuadro de herramientas
Para crear los objetos del interfaz de usuario de nuestra aplicacin, aadimos controles desde
el Cuadro de herramientas a un formulario. Inicialmente, el Cuadro de herramientas se
encuentra ubicado en el lado izquierdo del entorno de desarrollo. Hay varias pestaas para
diferentes categoras de controles, como Todos los formularios Windows Forms, Controles
comunes, Contenedores, Mens y barras de herramientas, Datos, etc.
El Cuadro de herramientas contiene diversos controles que podemos utilizar para aadir
ilustraciones, etiquetas, botones, cuadros de lista, barras de desplazamiento, mens y formas
geomtricas a un interfaz de usuario. Cada control que aadimos a un formulario se convierte en
un objeto de interfaz de usuario programable en nuestra aplicacin. Estos objetos son visibles
para los usuarios cuando la aplicacin se ejecuta y funcionan como los objetos estndares de
cualquier aplicacin basada en Windows.
Pg. 14
Ventana de Propiedades
La ventana de Propiedades muestra una lista de las propiedades que pueden configurarse
para el formulario o control seleccionado y que podemos modificar mientras creamos o
editamos la aplicacin. Una propiedad describe una caracterstica de un objeto, como el tamao,
ttulo o color.
Para situarte en las propiedades de un control o formulario en concreto tenemos varias
posibilidades. Hacer doble clic sobre el control (o formulario) siempre que la ventana de
propiedades est desplegada, elegir la opcin Propiedades si hacemos clic con el botn
secundario (en el caso de que la ventana de Propiedades no estuviese desplegada), elegir el
control desde el combo de la propia ventana como puedes apreciar en la figura.
Nota. Si la ventana Propiedades no est visible, haz clic en Ventana Propiedades en el men
Ver o pulsa la tecla F4, y si est visible pero no desplegada, acrcate a ella con el puntero del
ratn y se desplegar.
Observa que las propiedades se pueden visualizar por orden alfabtico o agrupadas por
categoras, dependiendo del icono elegido, pero independientemente de cmo las agrupes,
siempre la primera es la asociada al nombre del control (propiedad Name). Para cambiar en la
forma de verlas haz clic sobre los iconos correspondientes:
Pg. 15
Control
Propiedad
Valor actual
Nuevo valor
Formulario
Text
Form1
Mi primer programa
Label1
Text
Label1
Cantidad de saludos
Label2
Text
Label2
Name
Button1
lblCantSaludos
BackColor
Control
Text
Button1
&Aceptar
Name
Button2
Text
Name
btnAceptar
Button2
&Fin
btnFin
Pero, al igual que antes, aunque hagas clic sobre algn control, no pasa nada. Para ello
debemos incorporar el cdigo necesario. Cmo lo conseguimos? Gracias al Editor de cdigo.
Antes de continuar vamos a guardar el proyecto. Es una buena costumbre ir guardando de
vez en cuando. Como buen@s informtic@s no debemos dejar que la mala suerte nos tire al
traste un buen rato de trabajo.
Te saldr una nueva ventana del tipo:
De nuevo te aconsejo que (si no lo habas hecho antes) cambies el nombre del proyecto y en
cuanto a la Ubicacin elijas la carpeta o lugar del disco que a ti te interese utilizando el botn de
examinar. Si no lo haces, por defecto se guardar en la carpeta visual studio que ha creado
VS.Net.
Pg. 16
Editor de cdigo
VS .NET proporciona un Editor de cdigo en el que escribir y mantener el cdigo de nuestro
proyecto. Cada formulario tendr su propio editor de cdigo distinto, facilitando la
organizacin, visualizacin y desplazamiento por el cdigo.
Este Editor contiene dos listas
desplegables en la parte superior de la
ventana: la lista Nombre de Clase a la
izquierda y la lista Nombre de mtodo a la
derecha. Nombre de Clase muestra todos los
controles del formulario asociado. Si
hacemos clic en el nombre de un control de
la lista, Nombre de mtodo muestra los
eventos de dicho control (los eventos son
acciones que el control puede realizar y que
nuestra aplicacin puede interpretar).
Utilizando estas listas conjuntamente, podemos localizar rpidamente y editar el cdigo de
nuestra aplicacin.
Cmo abrimos esta ventana?
En el Explorador de soluciones, tras elegir el
formulario sobre el que se quiere editar su
cdigo, haciendo clic en el icono correspondiente
al cdigo.
(el de su derecha es para ver en
modo diseo).
En el men Ver, clic en Cdigo.
Haciendo doble clic sobre el formulario. Automticamente aparecer tambin la
misma ventana.
Haciendo doble clic sobre un control. En ese caso aparecer la ventana de cdigo con
algo semejante a lo que puedes apreciar en la figura: (Supongamos que el clic ha sido
sobre el botn btnAceptar).
Pg. 17
Lo que vamos a hacer ahora, es escribir el cdigo que se ejecutar cuando se haga click en
los dos botones. Este evento se producir si se hace un click propiamente dicho, es decir con el
ratn, o bien porque se pulse Intro o la barra espaciadora cuando el botn tenga el foco. La
nomenclatura, para los eventos de VB.Net siguen el siguiente "esquema": [nombre del control]
[guin bajo] [nombre del evento] Pero esto slo es una sugerencia que VB.Net nos hace, en las
versiones anteriores no era una sugerencia, era una imposicin. Podemos dejar el nombre que
VB.Net nos sugiere o podemos poner el nombre que nosotros queramos; lo importante aqu es
la parte final de la lnea de declaracin del procedimiento: Handles btnAceptar.Click, con esto
es con lo que el compilador/intrprete de VB.Net sabe que este procedimiento es un evento y
que dicho evento es el evento Click del objeto btnAceptar.
Copia el siguiente cdigo y ejecuta el programa.
Ejecuta el programa y haz clic sobre el botn Aceptar, vers cmo obtienes algo semejante a:
Pg. 18
Si por el contrario ahora pulsas sobre el botn de Cancelar, vers como el formulario se
cierra. Observa que si pulsas <ALT> a o <ALT>f se corresponder con el clic del botn
Aceptar y Fin respectivamente (por tener la letra subrayada, lo cual hemos conseguido gracias a
que en la propiedad Text pusimos la & antes de la letra a resear (&Aceptar o &Fin
respectivamente).
Ahora veamos con detalle el cdigo que hemos usado en los dos eventos:
Para el evento clic del botn con nombre btnAceptar hemos escrito:
MessageBox.Show("Hola mundo", "Saludo", MessageBoxButtons.OK,
MessageBoxIcon.Exclamation)
lblCantSaludos.Text = CInt(lblCantSaludos.Text) + 1
MessageBox que es una clase, cuya tarea es mostrar en un cuadro de dilogo lo que le
indiquemos en el primer parmetro (en nuestro caso "Hola mundo"), con ttulo Saludo en el 2
parmetro, con el botn de
Pg. 19
Pg. 21
Y recuerda! Si estamos hablando de una propiedad (los dos primeros ejemplos) se utiliza el
operador de asignacin = (le damos un valor), pero si es un mtodo (el tercero) no, ya que en
estos casos se trata de realizar una accin, no recibir un valor.
Propiedades
Veremos ciertas propiedades de los formularios, pero recuerda que tanto para formularios
como controles, siempre puedes consultarlas empleando las mltiples formas de ayuda que nos
da el propio Visual Studio.
Name. Cadena de caracteres con el nombre identificativo del objeto utilizado en el
cdigo fuente de la aplicacin. Asignaremos siempre un nombre que empiece por frm.
Ejemplo: frmDatosPers
El nombre tiene que seguir las reglas de los identificadores. Es decir frmN1 no sera un
nombre de formulario vlido.
El valor de esta propiedad se asignar obligatoriamente en tiempo de diseo, en la
Ventana de Propiedades.
Text. Texto que se visualiza en la barra de ttulo del formulario. En este caso se suele
dar valor en tiempo de diseo pero podemos tambin hacerlo en tiempo de ejecucin.
Ejemplo: Si deseamos que un formulario de nombre frmPrincipal reciba el ttulo:
Ejemplo de Uso de operadores lo haremos con una de las 2 instrucciones siguientes,
dependiendo de si nos encontramos en el mismo formulario o en otro.
Me.Text = "Ejemplo de Uso de operadores" ' Nos encontramos en el mismo
formulario
frmPrincipal.Text = "Ejemplo de Uso de operadores" ' Si estamos en otro
formulario
Pg. 22
Dependiendo del valor elegido nos encontraremos con un formulario sin borde, con
barra de ttulo pero con el tamao fijo (Fixed)o modificable (Sizable), con los botones
de Minimizar, Restaurar o no,
ControlBox. Propiedad lgica (admite los valores True o False), que sirve para
indicar si el formulario dispondr de un men de control, es decir, los iconos que
aparecen a la derecha del formulario para permitir Minimizar, Restaurar o Cerrarlo. Su
valor por defecto es True.
Pg. 23
Mtodos
En cuanto a los mtodos, uno de los ms utilizado es el mtodo Close, que lo que hace es
cerrar o descargar el formulario. Dependiendo del formulario al que hagamos referencia,
pondremos la palabra Me (si estamos hablando del mismo sobre el que se escribe el cdigo) u
otro, ejemplo: frmDatos.Close significara que debe cerrar el formulario con ese nombre.
Private Sub btnFin_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnFin.Click
Me.Close() ' cierra (descarga) el formulario actual
End Sub
Otros mtodos que tambin vamos a utilizar mucho son: Show y ShowDialog que sirven
para lo contrario, mostrar un formulario en pantalla.
Private Sub btnCargar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnCargar.Click
frmDatos.Show()' carga en pantalla el formulario frmDatos
End Sub
Eventos
Y por ltimo veamos algunos de procedimientos orientados a los eventos que ms vamos a
utilizar:
Load: Este evento se produce cuando el formulario se carga en memoria, y lo que
programaremos es para indicar las acciones que queremos realizar cuando esto ocurra. Veamos
un ejemplo:
Private Sub frmHolaMundo_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Load
' Instrucciones que queremos ejecutar al cargarse el formulario
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.FixedSingle ' Borde fijo de
una sola lnea
Me.lblCantSaludos.Text = 0 ' La etiqueta comienza con este valor
End Sub
Pg. 24
Controles ms habituales
Como habr comprobado, el nmero de controles del cuadro de herramientas es muy
numeroso, por lo que en los prximos apartados, vamos a trabajar con los que se consideran
controles bsicos o estndar, dada su gran frecuencia de uso.
Recuerda que cada vez que insertemos un control, tomar una serie de propiedades por
defecto (nombre incluido), que podremos cambiar para adaptar a los requerimientos de la
aplicacin.
La siguiente tabla relaciona este conjunto de controles bsico, junto a una breve descripcin.
Control
Descripcin
Button
Botn de pulsacin
Label
Etiqueta de literal
lbl - lblDatosPersonales
TextBox
Cuadro de texto
txt - txtNombre
ListBox
Lista de valores
lst - lstCiudades
ComboBox
CheckBox
Casilla de verificacin
chk - chkTrabajando
RadioButton
Botn autoexcluyente
rad - radMujer
GroupBox
grb grbDatos
Button
Este control representa un botn de pulsacin. Entre el nutrido conjunto de propiedades de
este control, destacaremos las siguientes.
Text. Cadena con el ttulo del botn.
TextAlign. Alineacin o disposicin del ttulo dentro del rea del botn; por defecto
aparece centrado.
BackColor. Color de fondo para el botn.
Cursor. Permite modificar el cursor del ratn que por defecto tiene el botn.
Image. Imagen que podemos mostrar en el botn como complemento a su ttulo, o
bien, en el caso de que no asignemos un texto al botn, nos permitir describir su
funcionalidad.
Pg. 25
ImageAlign. Al igual que para el texto, esta propiedad nos permite situar la imagen
en una zona del botn distinta de la central, que es en la que se ubica por defecto.
BackgroundImage. Imagen de fondo para el botn.
FlatStyle. Tipo de resaltado para el botn. Por defecto, el botn aparece con un cierto
relieve, que al ser pulsado, proporciona el efecto de hundirse y recuperar nuevamente
su estado, pero podemos, mediante esta propiedad, hacer que el botn se muestre
en modo plano, con un ligero remarcado al pulsarse, etc.
Font. Cambia el tipo de letra y todas las caractersticas del tipo elegido, para el
texto del botn.
La siguiente figura muestra un ejemplo de control Button, sobre el que se han modificado
algunos valores por defecto de sus propiedades.
Y generalmente para qu queremos un botn? Pues para que el programa realice alguna
tarea cuando se presiona sobre l.
Para programar esto, tendremos el evento ms utilizado de los botones, que es el evento
Click, al que le aplicaremos el subprograma asociado, en la forma:
Private Sub btnFin_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnFin.Click
Me.Close() ' cierra (descarga) el formulario actual
End Sub
Label
El control Label o Etiqueta, muestra un texto informativo al usuario. Podemos utilizar este
control como complemento a otro control, por ejemplo, situndolo junto a un TextBox, de modo
que indiquemos al o a la usuaria el tipo de dato que esperamos que introduzca en la caja de
texto.
Se trata de un control esttico; esto quiere decir que el usuario o usuaria no suele
interaccionar con l, a diferencia, por ejemplo, de un control Button, sobre el que actuamos
pulsndolo; o de un TextBox, en el que podemos escribir texto.
Una de sus propiedades es BorderStyle, que permite definir un borde o recuadro alrededor
del control, o que dicho borde tenga un efecto 3D; por defecto se muestra sin borde. Veamos
unos ejemplos en la Figura
Controles Label.
Pg. 26
TextBox
Un control TextBox muestra un recuadro en el que podemos introducir texto. Para poder
escribir texto en un control de este tipo, debemos darle primeramente el foco, lo que
detectaremos cuando el control muestre el cursor de escritura en su interior.
Entre las propiedades disponibles por este control, destacaremos las siguientes.
Text. Cadena con el texto del control.
Multiline. Permite establecer si podemos escribir una o varias lneas. Por defecto
contiene False, por lo que slo podemos escribir el texto en una lnea.
Enabled. Contiene un valor lgico mediante el que indicamos si el control est o no
habilitado para poder escribir texto sobre l.
ReadOnly. Permite indicar si el contenido del control ser de slo lectura o bien,
podremos editarlo.
CharacterCasing. Esta propiedad, permite que el control convierta automticamente
el texto a maysculas o minsculas segn lo estamos escribiendo.
MaxLength. Valor numrico que establece el nmero mximo de caracteres que
podremos escribir en el control.
PasswordChar. Carcter de tipo mscara, que ser visualizado por cada carcter que
escriba el usuario en el control. De esta forma, podemos dar a un cuadro de texto
el estilo de un campo de introduccin de contrasea.
AutoSize. Cuando esta propiedad tenga el valor True, al modificar el tamao del tipo
de letra del control, dicho control se redimensionar automticamente, ajustando su
tamao al del tipo de letra establecido.
CharacterCasing. Tiene 3 posibles valores Normal, Lower o Upper para indicar que
el carcter tecleado se escriba como se teclea, en minsculas o maysculas.
ScrollBar: Permite aadir barras de desplazamiento. Posibles valores: None, Vertical,
Horizontal o Both. Para ser efectivo, la caja de texto deber tener establecida la
propiedad MultiLine a True y si ponemos Both deberemos cambiar la propiedad
WordWrap a False.
Foco de entrada
Para que las pulsaciones de teclado puedan ser recibidas por un determinado control,
dicho control debe tener lo que se denomina el foco de entrada.
El modo de dar a un control el foco de entrada, consiste en hacer clic sobre l, o bien, pulsar
la tecla [TAB], pasando el foco hasta el control deseado. Cuando un control recibe el
foco, el sistema operativo lo remarca visualmente o en el caso de controles de escritura,
muestra el cursor de escritura en su interior.
La siguiente figura muestra un formulario con varios controles TextBox, a los cuales se
han aplicado diferentes efectos mediante sus propiedades.
Pg. 27
Observa, que en el botn Foco nombre, que acabamos de mencionar, la letra F se encuentra
subrayada, actuando de acelerador o hotkey. De este modo, no es necesario pulsar con el
ratn sobre ese botn para ejecutarlo, basta con pulsar la tecla [CONTROL] junto a la letra
subrayada para conseguir el mismo efecto.
Para definir una tecla aceleradora en un control, debemos anteponer el carcter & a la letra
que vamos a definir como acelerador, en este ejemplo se ha logrado con &Foco nombre.
Por otro lado, mediante el botn btnSoloLectura vamos a activar/desactivar la propiedad
ReadOnly del TextBox txtNombre, cambiando el estado de dicha propiedad en cada pulsacin
del botn.
Private Sub btnSoloLectura_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnSoloLectura.Click
Me.Nombre.ReadOnly = Not Me.Nombre.ReadOnly ' Cambia el estado de la
propiedad ReadOnly de True a False o viceversa (a lo contrario de lo que estaba)
End Sub
Al establecerse esta propiedad en true, el usuario no puede cambiar el contenido del control
en tiempo de ejecucin, pero si puede darle el foco y, por ejemplo, Copiar su texto en el
portapapeles gracias al tpico Copiar.
Otra cosa diferente es deshabilitar totalmente el control, no permitiendo el acceso al mismo,
ni tan siquiera recibira el foco.
Supongamos que deseamos hacer esto con la caja de texto txtApellidos. Escribe el cdigo
correspondiente para el evento Clic del botn btnActivar.
Pg. 28
Sugerencia: Piensa como sera este subprograma si quisiramos controlar que la, solo se
pudiese teclear una vez.
Por otra parte est el evento TextChanged, que se produce, como su nombre indica, cada vez
que alguien cambia el texto de la caja de texto. Veamos una forma de trabajar con l:
Private Sub txtSueldo_TextChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles txtSueldo.TextChanged
' Se produce cada vez que cambia el texto de la caja de texto, porque lo cambia
' (escribiendo sobre ella o con Pegar) la o el usuario o por el propio programa
' en instrucciones como txtSueldo.Text = 1.600,20
If txtSueldo.Text = "" Then Exit Sub ' Si se ha quedado en blanco no lo
' consideramos error
If Not IsNumeric(txtSueldo.Text) Then
MessageBox.Show(txtSueldo.Text & " no es un dato numrico", "Atencin",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
txtSueldo.Text = "" ' limpiamos el dato de la caja de texto
End If
End Sub
Y ahora tal vez te preguntes, para qu vamos a poner los 2 subprogramas en la misma caja
de texto?, con uno vale. Habr ocasiones en que as sea, pero analicemos las diferencias:
En el caso del KeyPress, si se pulsa una tecla errnea solo se anula esa tecla, no hace falta
borrar todo lo que ya contena. Vale, pues entonces por qu no dejar solo el KeyPress? Piensa
en el caso, muy probable de que en lugar de teclear en la caja de texto se haga el tpico Pegar.
En ese caso, no se habr producido el evento KeyPress y por tanto no se habra detectado el
error.
Y por ltimo, si ponemos ambos, cul se produce primero? Pues el KeyPress. Es decir, si en
el ejemplo anterior, se pulsa una letra, el KeyPress detectar que no es vlida y no se modificar
la caja de texto (por lo que no se ir al otro subprograma) y si el dato es vlido ir a los 2.
Y ahora piensa que hara el siguiente ejemplo:
Private Sub txtNombre_KeyPress(ByVal sender As System.Object, ByVal e As
System.Windows.Forms.KeyPressEventArgs) Handles txtNombre.KeyPress
If e.KeyChar = "" Then e.KeyChar = "n"
If e.KeyChar = "" Then e.KeyChar = "N"
End Sub
Pg. 29
El control de este formulario, que vamos a emplear para las operaciones de seleccin es
txtOrigen. En primer lugar, y aunque no se trata de una seleccin de texto, usaremos el evento
TextChanged visto anteriormente, pero ahora de otra manera. En este caso lo usaremos para
contar la cantidad de caracteres escritos y mostrarlos en un Label. Ver Cdigo fuente.
' al cambiar el texto del control se produce este evento
Private Sub txtOrigen_TextChanged(ByVal sender As Object, ByVal e As
System.EventArgs) Handles txtOrigen.TextChanged
' calculamos la longitud del texto escrito
Me.lblContador.Text = Me.txtOrigen.TextLength
End Sub
Pg. 30
Si lo ejecutas podrs encontrarte con algo semejante a las siguientes imgenes. De todas
formas observa que si has seleccionado un texto en cualquiera de las dos modalidades (figura de
la izquierda) y aparecen los datos correspondientes en las etiquetas, al pulsar, por ejemplo, sobre
el botn Seleccionar se mantendran. Se te ocurre como limpiarlos?
Pg. 31
CheckBox
Este control muestra una casilla de verificacin, que podemos marcar para establecer un
estado. Generalmente el estado de un CheckBox es marcado (verdadero) o desmarcado (falso),
sin embargo, podemos configurar el control para que sea detectado un tercer estado, que se
denomina indeterminado, en el cual, el control se muestra con la marca en la casilla pero en
un color de tono gris.
Las propiedades remarcables de este control son las siguientes.
Checked. Valor lgico que devuelve True cuando la casilla est marcada, y False
cuando est desmarcada.
CheckState. Valor del tipo enumerado CheckState, que indica el estado del control.
Checked, marcado; Unchecked, desmarcado; e Indeterminate, indeterminado.
ThreeState. Por defecto, un control de este tipo slo tiene dos estados, pero
asignando True a esta propiedad, conseguimos que sea un control de tres estados.
CheckAlign. Permite establecer de modo visual la ubicacin de la casilla de
verificacin dentro del rea del control.
Como detalle destacable de las propiedades Checked y CheckState, si modificamos desde
cdigo sus valores, conseguiremos alterar el estado de la casilla del control.
Pg. 32
Por su parte, el control chkMostrarSaludo, definido con tres estados, muestra, al estar
marcado, una cadena de saludo en la etiqueta lblSaludo; elimina la cadena al desmarcarlo; y
muestra los 4 primeros caracteres al entrar en el estado indeterminado. El evento
CheckStateChanged es el que debemos de utilizar para detectar el estado del CheckBox en cada
ocasin. Para mantener el valor de la cadena a mostrar, utilizamos una constante global.
Const saludo = "Hola 1DAM"
' Este evento se produce cuando cambia el estado de la casilla.
' Si usamos el CheckedChanged al marcar Indeterminado no se provoca el evento
Private Sub chkMostrarSaludo_CheckStateChanged(ByVal sender As Object, ByVal e As
System.EventArgs) Handles chkMostrarSaludo.CheckStateChanged
Select Case Me.chkMostrarSaludo.CheckState
Case CheckState.Checked
Me.lblSaludo.Text = saludo
Case CheckState.Unchecked
Me.lblSaludo.Text = ""
Case CheckState.Indeterminate
Me.lblSaludo.Text = saludo.Substring(0, 4) ' Coge los 4 primeros caracteres
End Select
End Sub
RadioButton y GroupBox
Los controles RadioButton nos permiten definir conjuntos de opciones autoexcluyentes, de
modo que situando varios controles de este tipo en un formulario, slo podremos tener
seleccionado uno en cada ocasin.
Vamos a crear un proyecto de ejemplo con el nombre PrRadioButton, en el que situaremos
dentro de un formulario, una serie de controles RadioButton y un TextBox, de modo que
mediante los RadioButton cambiaremos el tipo de fuente y color del cuadro de texto. La Figura
muestra un diseo inicial del formulario. Por cierto, observa que el RadioButton azul tiene el
color azul ms largo que el resto. Trabaja con la propiedad AutoSize y vers el porqu.
Pg. 33
El evento CheckedChanged, al igual que ocurra con los controles CheckBox, ser el que
tendremos que escribir para ejecutar el cdigo en respuesta a la pulsacin sobre un control
RadioButton. El Cdigo fuente siguiente muestra los eventos correspondientes a los controles
de radio de este ejemplo. Para cambiar el tipo de fuente, instanciamos un objeto Font y lo
asignamos a la propiedad Font del TextBox; mientras que para cambiar el color, utilizamos la
estructura Color y la propiedad BackColor, tambin del TextBox.
Private Sub rbtTahoma_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles rbtTahoma.CheckedChanged
Me.txtNombre.Font = New Font("Tahoma", 12)
End Sub
Private Sub rbtGaramond_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles rbtGaramond.CheckedChanged
Me.txtNombre.Font = New Font("Garamond", 8)
End Sub
Private Sub rbtComic_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles rbtComic.CheckedChanged
Me.txtNombre.Font = New Font("Comic Sans MS", 15)
End Sub
Private Sub rbtVerde_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles rbtVerde.CheckedChanged
Me.txtNombre.BackColor = Color.Green
End Sub
Pg. 34
ListBox
Un control ListBox contiene una lista de valores, de los cuales, el o la usuaria puede
seleccionar uno o varios simultneamente. Entre las principales propiedades de este control,
podemos resaltar las siguientes.
Items. Contiene la lista de valores que visualiza el control. Se trata de un tipo
ListBox.ObjectCollection, de manera que el contenido de la lista puede ser tanto tipos
carcter, como numricos y objetos de distintas clases. Al seleccionar esta propiedad
en la ventana de propiedades del control y pulsar el botn que contiene, podemos
introducir en una ventana elementos para el control
El control quedara por lo tanto con valores asignados en la etapa de diseo, como
muestra la siguiente figura:
Sorted. Cuando esta propiedad contiene el valor True, ordena el contenido de la lista.
Cuando contiene False, los elementos que hubiera previamente ordenados,
permanecen con dicho orden, mientras que los nuevos no sern ordenados.
Pg. 35
Pg. 36
Cada vez que hacemos clic en alguno de los valores, se produce el evento
SelectedIndexChanged, que utilizamos para mostrar en este caso, el nombre del elemento o
elementos en el ttulo del formulario, como muestra el siguiente cdigo. Primero averiguaremos
cuantos hay seleccionados gracias a cualquiera de las 2 propiedades que contienen las
colecciones: SelectedIndices o SelectedItems que contienen los ndices o elementos
seleccionados respectivamente.
Si solo tenemos un elemento seleccionado podemos utilizar la propiedad SelectedItem o si
lo necesitase SelectedIndex que contienen el texto o ndice del elemento seleccionado, pero en
el caso de que haya varios, debemos recurrir a las colecciones antes comentadas.
' este evento se produce cada vez que se cambia el
' ndice seleccionado del ListBox
Private Sub lstValores_SelectedIndexChanged(ByVal sender As System.Object, ByVal
e As System.EventArgs) Handles lstValores.SelectedIndexChanged
' mostrar en el ttulo del formulario el valor o valores seleccionados
If lstValores.SelectedItems.Count = 0 Then
' No hay ninguno seleccionado
Me.Text = "No hay elementos seleccionados"
ElseIf lstValores.SelectedIndices.Count = 1 Then
' Hay solo uno seleccionado, usamos la propiedad SelectedItem
Me.Text = "Elemento seleccionado: " & Me.lstValores.SelectedItem
Else
' Hay varios, debemos recorrer los distintos elementos
Me.Text = "Elementos seleccionados "
For i As Integer = 0 To Me.lstValores.SelectedItems.Count - 1
Me.Text &= Me.lstValores.SelectedItems(i) & " "
Next
End If
End Sub
Pg. 37
Pg. 38
ComboBox
El ComboBox es un control basado en la combinacin (de ah su nombre) de dos controles
que ya hemos tratado: TextBox y ListBox.
Un control ComboBox dispone de una zona de edicin de texto y una lista de valores, que
podemos desplegar desde el cuadro de edicin.
El estilo de visualizacin por defecto de este control, muestra el cuadro de texto y la
lista oculta, aunque mediante la propiedad DropDownStyle podemos cambiar dicho estilo. La
siguiente figura muestra un formulario con diversos ComboBox, cada uno con diferente estilo.
Pg. 39
PictureBox
Se dice que una imagen vale ms que mil palabras y, de hecho, muchos programas las
utilizan para transmitir informacin. Hay varias maneras de mostrar imgenes en VB.Net: la
ms comn es utilizando un control PictureBox.
Los controles PictureBox actan como un contenedor para las imgenes; se elige la imagen
que se va a mostrar estableciendo la propiedad Image. Como casi siempre podemos La
establecer esta propiedad en la ventana Propiedades o escribiendo el cdigo para decirle al
programa qu imagen se va mostrar.
Antes de agregar una imagen a un control PictureBox, generalmente se agregar el archivo
de imagen al proyecto como un recurso. Una vez que se agrega un recurso al proyecto,
podremos volver a utilizarlo cuantas veces lo deseemos. Observa el formulario de ejemplo, en el
cual hemos puesto la misma imagen en todos los controles.
As que para aadir una imagen vete a la propiedad Image (en la ventana de propiedades) y
pulsa sobre el icono de seleccin:
Nos aparecer una ventana como la que se muestra a continuacin, en la cual podemos
seleccionar la imagen solo para este recurso (en Recurso local), o an mejor en Archivo de
recursos, como puedes ver aqu:
Otra propiedad til para el control PictureBox es SizeMode, que se puede utilizar para
expandir, centrar o ampliar la imagen dentro del control PictureBox y que puede coger los
siguientes valores.
Observa el siguiente ejemplo en el que todos los controles tienen la misma imagen, pero con
distinto modo.
Nota. En todos los controles he puesto la propiedad BorderStyle a FixedSingle para que se
vea bien cmo es y qu tamao tiene el control. Si te fijas el de la derecha ni siquiera entra en el
formulario.
Pg. 40
Y por ltimo, cmo haremos si lo que deseamos es modificar una imagen de control pero
dependiendo de lo que elija el/la usuaria? O lo que es lo mismo, si queremos poner una imagen
en un control en tiempo de ejecucin. En ese caso necesitaremos conocer el nombre del fichero
que contiene la imagen (nombre con toda la ruta). E:\Fotos\Flores.jpg.
Tendremos varias formas de permitirle al o a la usuaria que lo haga, y generalmente
elegiremos el tpico Cuadro de Dilogo de Abrir, pero en este momento eso excede de nuestro
conocimiento, por lo que, tambin podramos hacer que se escribiera la ruta en una caja de
texto.
Por tanto, si dejamos que sea en la caja de texto donde introduce el nombre, con ruta, de la
imagen podramos hacer:
Private Sub btnCambiarImagen_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnCambiarImagen.Click
' Carga la imagen del fichero con nombre en la caja de texto
' Ejemplo: E:\Flores\amapola.jpg
Me.picFotoZoom.Image = Image.FromFile(txtImagen.Text)
End Sub
Pg. 41
Anclaje de controles
La propiedad Anchor, existente en un gran nmero de controles, nos permite anclar
dicho control a uno o varios bordes del formulario.
Cuando un control es anclado a un borde, la distancia entre el control y dicho borde ser
siempre la misma, aunque redimensionemos el formulario.
Para establecer esta propiedad, debemos pasar a la ventana de propiedades del control, y en
Anchor, pulsar el botn que dispone, y que nos mostrar una representacin de los bordes para
anclar.
Las zonas de color gris oscuro representan los bordes del control que ya estn anclados a
los bordes del formulario. Debemos marcar y desmarcar respectivamente estos elementos segn
los bordes que necesitemos anclar. Por defecto, los controles se encuentran inicialmente
anclados a los bordes superior e izquierdo (Top, Left), como hemos comprobado en la anterior
figura.
La figura muestra un ejemplo en el que vemos dos controles que tienen distintos tipos de
anclaje. Button1 tiene el anclaje normal: Top-Left, mientras que Button2 tiene slo Right, por
ello, su borde derecho siempre mantendr la misma distancia con ese borde del formulario
Al cambiar el tamao del formulario los botones se quedan anclados en el borde expresado
Acople de controles
A travs de la propiedad Dock de los controles, podremos acoplar un control a uno de los
bordes de un formulario, consiguiendo que dicho control permanezca pegado a ese borde del
formulario en todo momento.
Para seleccionar el tipo de acople, haremos clic en el botn que tiene la propiedad Dock en
la ventana de propiedades, y que nos mostrar un gua de los tipos de acople disponibles.
Pg. 42
Si por el contrario, no queremos dar el foco a un control pulsando [TAB], debemos asignar a
la propiedad TabStop de dicho control el valor False. Por defecto, TabStop vale True,
permitiendo de esta el paso de foco entre controles mediante la tecla [TAB]
Pg. 43
Cap 3. El lenguaje
Variables, definicin y entorno
En VB.Net se pueden usar variables para almacenar valores temporalmente durante la
ejecucin de una aplicacin. Las variables tienen un nombre (la palabra que utilizaremos para
referirnos al valor que contiene la variable) y un tipo de dato (que determina la clase de datos
que la variable puede almacenar)
VB.Net distingue entre maysculas y minsculas pero dependiendo de la declaracin que le
demos a la variable o/y control siempre la escribir as, lo cual es muy til para ver si realmente
la estamos escribiendo bien. Observa que a medida que escribimos (al finalizar cada palabra)
automticamente VB la reescribe como est definida.
Ejemplo: Supongamos que hemos declarado la variable Edad y la caja de texto txtEdad y en
nuestro programa escribimos la palabra edad o txtedad VB.Net, automticamente las reescribir
como estaban al comienzo (en estos casos con las E en maysculas), por lo que si nos
equivocamos y escribimos txtfedad al no reescribir nada en maysculas veramos que algo
hemos escrito mal.
De ah la importancia de jugar con maysculas y minsculas en las declaraciones de todos
nuestros controles y/o variables.
Es por todo lo anterior que VB.Net, de forma generalizada en la comunidad de
programador@s, opta por usar las denominadas Notacin Camel (Camello) a la hora de declarar
cualquier identificador (variable, control, clase, objeto, ).
Notacin Camel
La notacin Camel consiste en escribir los identificadores con la primera letra de cada
palabra en maysculas y el resto en minscula: EndOfFile. Se llama notacin Camel porque
los identificadores recuerdan las jorobas de un camello. Existen dos variantes:
Pg. 45
El nombre de una variable puede ser tan largo como queramos, hasta un mximo de 40
caracteres. En la versin VB.Net para Espaa se pueden usar incluso la y vocales acentuadas.
El nombre de una variable siempre debe comenzar por una letra o el guin bajo (_curso) y luego
puede ir seguido de letras, nmeros o guiones.
En el caso de las constantes, se
Atencin: En el caso de las constantes, se tiende a escribirla entera en maysculas: PI,
INSTITUTO, . para distinguirlas de las variables.
La declaracin de una variable es el proceso por el cual comunicamos al compilador que
vamos a crear una nueva variable en el programa.
Para declarar una variable utilizaremos la palabra clave Dim, Static, Private o Public
(dependiendo del lugar donde declaremos la variable y el mbito que queramos darle) seguida
del identificador o nombre que daremos a dicha variable.
Public Area As Integer ' variable global y pblica
Private Nombre As String ' variable global y privada
Function AreaTriangulo(ByVal base As Integer, ByVal altura As Integer) As Integer
Dim area As Integer ' variable local, se declara en cada llamada
'...
End Function
Sub LLamadas()
Static numVeces As Integer ' local, mantiene el valor anterior
numVeces += 1
MessageBox.Show(numVeces)
End Sub
Tipo correspondiente en
el entorno de .NET
Framework
Tamao
(bytes)
Rango de valores
Boolean
System.Boolean
Byte
System.Byte
Char
System.Char
Date
System.DateTime
Integer
System.Int32
-2.147.483.648 a 2.147.483.647
Long (entero
largo)
Short
System.Int64
System.Int16
-9.223.372.036.854.775.808
9.223.372.036.854.775.807
-32.768 a 32.767
Single (punto
flotante con
precisin simple)
Decimal
System.Single
System.Decimal
12
Pg. 46
Double
System.Double
(punto flotante con
precisin doble)
Object
System.Object
String (cadena
delongitud
variable)
System.String
-1,79769313486232E308 a
-4,94065645841247E-324 para valores
negativos; 4,94065645841247E-324 a
1,79769313486232E308 para valores positivos
Cualquier tipo
Si al declarar una variable no indicamos el tipo, por defecto tomar Object, que corresponde
al tipo de datos genrico en el entorno del CLR, y admite cualquier valor.
Segn lo visto, si declaramos una variable de tipo Byte e intentamos asignarle el valor 5899
se va a producir un error, ya que no se encuentra en el intervalo de valores permitidos para esa
variable. Esto puede llevar a preguntarnos: por qu no utilizar siempre Object y poder usar
cualquier valor?, o mejor para qu necesitamos asignar tipo a las variables?.
El motivo de tipificar las variables reside en que cuando realizamos una declaracin, el CLR
debe reservar espacio en la memoria para los valores que pueda tomar la variable. Si adems,
declaramos todas las variables como Object, los gastos de recursos del sistema sern mayores
que si establecemos el tipo adecuado para cada una, ya que como el CLR no sabe el valor que
puede tomar en cada ocasin la variable, debe realizar un trabajo extra de adecuacin,
consumiendo una mayor cantidad de recursos.
VS.NET dispone de una ayuda al asignar el tipo a una variable, que nos muestra la lista de
tipos disponibles para poder seleccionar uno sin tener que escribir nosotros el nombre. Al
terminar de escribir la palabra As, aparecer dicha lista, en la que pulsando las primeras letras
del tipo a buscar, se ir situando en los ms parecidos. Una vez encontrado, pulsaremos la tecla
Enter o Tab para aceptarlo.
Con esta tcnica de declaracin, todas las variables de la lnea tienen el mismo tipo de dato,
ya que no es posible declarar mltiples variables en la misma lnea que tengan distintos tipos de
dato.
Asignacin de valor
Para asignar un valor a una variable utilizaremos el operador de asignacin: el signo
igual ( = ), situando a su izquierda la variable a asignar, y a su derecha el valor.
En el caso de que queramos inicializar la variable en el momento de la declaracin, debemos
separar cada declaracin en una lnea, aunque coincidan en el valor de inicializacin:
Private num As Integer = 5 ' usaremos lneas independientes
Private edad As Integer = 5
Segn el tipo de dato de la variable, puede ser necesario el uso de delimitadores para
encerrar el valor que vamos a asignar.
Tipos numricos. Las variables de tipos de datos numricos no necesitan
delimitadores, se asigna directamente el nmero correspondiente. Si necesitamos
especificar decimales, utilizaremos el punto ( . ) como carcter separador para los
decimales
Pg. 47
Valor inicial
Toda variable declarada toma un valor inicial por defecto, a no ser que realicemos una
asignacin de valor en el mismo momento de la declaracin. A continuacin se muestran
algunos valores de inicio en funcin del tipo de dato que tenga la variable:
Numrico. Cero ( 0 ).
Cadena de caracteres. Cadena vaca ( "" ).
Fecha. 01/01/0001 0:00:00.
Lgico. Falso (False).
Objeto. Valor nulo (Nothing).
Por otro lado podemos, inversamente, inicializar una variable que ya tiene valor,
asignndole la palabra clave Nothing; con ello, la variable pasa a tener el valor por defecto o
inicial.
Dim Valor As String
Dim FechaActual As Date
Dim ValorLogico As Boolean
' asignar valores a variables
Valor = "mesa"
FechaActual = "10/8/2001"
ValorLogico = True
' inicializar de nuevo las variables a los valores por defecto
Valor = Nothing
FechaActual = Nothing
ValorLogico = Nothing
Pg. 48
End Sub
Si ahora estamos en otro formulario, ejemplo frmDatos no podremos usar ninguna de las
variables privadas num, nVeces o Direccin.
Private Sub DesdeOtroForm()
' Puede acceder a Edad pero debe saber que es del otro formulario
frmPrincipal.Edad = 20
frmPrincipal.Direccin = "Calle San Jorge s/n" ' ERROR. No puede acceder
End Sub
De todas formas recuerda que el VS.Net tenemos ayuda para todo, incluso en el momento en
que estamos escribiendo. Observa la siguiente imagen:
Pg. 49
Constantes
Existen dos tipos de constantes:
Pg. 50
Se puede colocar ms de una declaracin de constante en una nica lnea si se separa con
comas:
Public Const PI = 3.14, MAXPLANETAS = 9, DISTANCIA_PLANETA = 1.5E+19
A menudo, la expresin del lado derecho del signo igual ( = ) es un nmero o cadena literal,
pero tambin puede ser una expresin que d como resultado un nmero o una cadena. Se puede
incluso definir constantes en trminos de constantes previamente definidas:
Const PI2 = PI * 2
Operadores
Aritmticos: +, - ,*, / (divisin real), \ (divisin entera), Mod (resto), ^ (potencia) y
los operadores abreviados +=, -=, ^=. Estos ltimos los veremos un poquito ms
adelante, con la instruccin de asignacin.
Alfanumricos: & y +. Ambos indican lo mismo, concatenacin de cadenas.
Relacionales: =, <>, <, >, <=, >=, Like
Lgicos: Not (ser lo contrario del operando. True->False y viceversa), And (sera
cierto si lo son los dos operandos), Or (cierto si lo es 1 de los operandos), Xor (cierto
si es uno y solo uno de los operandos), AndAlso (semejante a And pero si el 1 es
False ya no sigue evaluando) y OrElse (semejante a Or pero si el primero es True ya
no sigue evaluando).
Ejemplos:
Dim Num1, Num2 As Integer, Cad As String, Positivo As Boolean
Num1 = Num2 * 3 ' Operador aritmtico, Num1 valdr el triple que Num2
If Num1 Mod 2 = 0 Then
' Estamos preguntando si el Resto de Num entre 2 es 0, es decir, si Num es par
Positivo = Num1 > 0 ' La variable Positivo guardar True si Num es > 0 y
False en otro caso
If Cad = "Hola" Or Cad = "Adios" Then ' Pregunta si Cad vale uno de esos dos
valores
Pg. 51
Vamos a incluir un cdigo que se deba ejecutar solo si el valor de la variable es numrico y
positivo. En ese caso pondramos algo semejante a:
If IsNumeric(num) And num > 0 Then ' Se rompe en el caso de que num no sea nmero
' Instrucciones del Then
Else
' Instrucciones del Else
End If
If IsNumeric(num) AndAlso num > 0 Then
Si la variable contiene un nmero en los dos casos funcionara igual, si es positivo hara lo
que se encuentre en el Then y si es negativo o 0 las instrucciones del Else.
Pero qu ocurre si la variable nunca ha recibido valor (estara con la cadena vaca ) o un
valor que no se pueda convertir a numrico (ejemplo hola)? En ese caso en el primer ejemplo,
y dado que debe hacerse ambas preguntas, al comparar (string) con 0 (numrico) se
romper. Sin embargo, en el segundo caso, al ver que no es numrico (primera parte False) ni
siquiera intenta hacer la segunda pregunta.
Pg. 52
Prioridad de operadores
Dentro de una lnea de cdigo que contenga varias operaciones, estas se resolvern en un
orden predeterminado conocido como prioridad de operadores. Dicha prioridad se aplica tanto
entre los operadores de un mismo grupo como entre los distintos grupos de operadores.
Los operadores aritmticos se ajustan a la prioridad indicada en la siguiente tabla,
considerando que la prioridad va de mayor a menor, es decir, la potencia se ejecuta antes que
la suma..
Prioridad de operadores aritmticos
Potenciacin ( ^ )
Negacin ( - )
Multiplicacin y divisin real ( * , /)
Divisin entera ( \ )
Resto de divisin ( Mod )
Suma y resta ( + , - )
Y por ltimo, cuando una expresin contenga operadores de distintos grupos, estos se
resolvern en el siguiente orden.
Prioridad entre operadores de distintos grupos
Aritmticos
Concatenacin
Comparacin
Lgicos
Dim Resultado As Boolean
Resultado = 30 + 5 * 5 > 100 And 52 > 10
' devuelve: False
Pg. 53
primer lugar. De esta forma, se resolvern en primer lugar las operaciones que se encuentren en
los parntesis ms interiores, finalizando por las de los parntesis exteriores. Es importante tener
en cuenta, que dentro de los parntesis se seguir manteniendo la prioridad explicada
anteriormente.
El cdigo siguiente en condiciones normales, devolvera False como resultado. Sin embargo,
gracias al uso de parntesis, cambiamos la prioridad predeterminada, obteniendo finalmente
True.
Dim Resultado As Boolean
Resultado = ((30 + 5) * 5 > 100) And (52 > 200 / (2 + 5)) ' devuelve: True
Comentarios
Como ya hemos visto en todos los ejemplos anteriores en VB.Net cada lnea de comentario
comienza con un apstrofo ('). Ejemplo:
' Esto es un comentario
Es muy cmodo utilizar los iconos Bloque con comentarios y Bloque sin comentarios
para, si hemos seleccionado un conjunto de instrucciones, poner o quitar el a todo ese
conjunto de instrucciones, convirtindolas /retirndolas por tanto en comentarios.
Ejemplo: Si tenemos seleccionado el texto que aparece en la figura y pulsamos el botn
Bloque con comentarios automticamente se escribir como aparece a la derecha.
Instrucciones en VB.Net
En principio en VB.Net cada instruccin se escribe en una y solo una lnea.
Si deseamos escribir dos instrucciones en una misma lnea deberemos separarlas por el
carcter :
Ejemplo.
pal = "hola" :
n = 2
Por lo mismo, si deseamos cortar una instruccin para que ocupe ms de una lnea debemos
aadir el carcter _.
Ejemplo. Deseamos asignar una concatenacin de cadenas en una caja de texto, y queremos
romper la lnea.
txtDireccin.Text = txtCalle.Text & " " & txtNum.Text & " " & _
txtPiso.Text & " " & txtLetra.Text
Pg. 54
Con esto, estamos indicndoles al VB que: calcula lo que actualmente vale la variable
nVeces , smale 1 y el resultado de esa suma, lo guarda de nuevo en la variable nVeces..
Por tanto, suponiendo que nVeces valiese 10, despus de esta asignacin, su valor ser 11,
(es decir 10 que vala antes ms 1 que le sumamos).
Esto ltimo se llama incrementar una variable, y el vb.NET tiene su propio operador para
estos casos, es decir cuando lo que asignamos a una variable es lo que ya haba antes ms el
resultado de una expresin:
nVeces += 1
Aunque tambin se pueden usar: *=, /=, -=, etctera, dependiendo de la operacin que
queramos hacer con el valor que ya tuviera la variable.
Por tanto i = i * 2, es lo mismo que i *= 2
Si deseamos escribir en ms de una lnea (lo habitual) debemos indicar el final del If con su
correspondiente End If. Observa adems que en VB el If tiene tres posibilidades, solo la parte
del Then, con Then y Else o con la opcin ElseIf, siempre que se escriba junto. Si lo separamos
estamos entrando en un segundo If que por tanto necesitar su propio End If.
If condicin Then
instrucciones
End If
If condicin Then
instrucciones
Else
instrucciones_else
End If
If condicin Then
instrucciones
ElseIf condicin-n Then
instrucciones_elseif
[Else
[instrucciones_else]
End If
La condicin es generalmente una expresin booleana, pero puede ser cualquier expresin
que pueda ser evaluada a un valor numrico, ya que un valor 0 es considerado como False y un
valor <> 0 como True. Si la condicin es verdadera se ejecutan las sentencias que estn a
Pg. 55
continuacin de Then y si la condicin es falsa las que estn a continuacin del Else si esta
clusula ha sido especificada o nada en caso contrario.
Ejemplos:
' If sin Else
If Not IsNumeric(txtNum.Text) Then
MessageBox.Show("Dato errneo")
txtNum.SetFocus()
Exit Sub
End If
' If con ElseIf y con Else
If txtNum.Text > 0 Then
MessageBox.Show("Positivo")
ElseIf txtNum.Text < 0 Then
MessageBox.Show("Negativo")
Else
MessageBox.Show("Vale 0")
End If
' If con Else
If txtNum.Text Mod 2 = 0 Then
MessageBox.Show("Par")
Else
MessageBox.Show("Impar")
End If
Pg. 56
lista_expresin en ms de una clusula Case, slo se ejecutan las instrucciones que siguen a la
primera coincidencia.
Aunque no es necesario, es buena idea tener una instruccin Case Else en el bloque Select
Case para controlar valores imprevistos de expresin_prueba.
Se pueden utilizar expresiones mltiples o intervalos en cada clusula Case. Por ejemplo, la
lnea siguiente es vlida:
Case 1 To 4, 7 To 9, 11, 13, Is > MaxNumber
' Ser cierto para los valores entre 1 y 4, de 7 a 9, el 11, el 13 y los mayores
que MaxNumber
Las instrucciones Select Case se pueden anidar. Cada instruccin Select Case debe tener su
correspondiente instruccin End Select.
Ejemplo:
Dim Nmero As Byte
Nmero = txtNum.Text
' Supongamos que en la caja de texto tenemos el nmero 6
Select Case Nmero
' Evala Nmero.
Case 1 To 5
' Nmero entre 1 y 5, inclusive.
lblSalida.Caption = "Entre 1 y 5"
Case 6, 7, 8
' Nmero entre 6 y 8. 'Esta ser la clusula Case cuyo valor
es True.
lblSalida.Caption = "Entre 6 y 8"
Case 9 To 10
' Nmero es 9 10.
lblSalida.Caption = "Mayor que 8"
Case Else
' Otros valores.
lblSalida.Caption = "Otro valor"
End Select
Recordemos que en VB.Net podemos poner ms de una instruccin siempre que aadamos
los : por lo que esta instruccin puede ponerse. A la vez observa que si se permite que un
valor se cumpla en dos clusulas Case se ejecutar solo para la primera. En este caso si Nmero
vale 10 la etiqueta se quedar con el valor Entre 9 y 10 y no Mayor o igual a 10
Select Case Nmero
' Evala Nmero.
Case 1 To 5 : lblSalida.Caption = "Entre 1 y 5"
Case 6, 7, 8 : lblSalida.Caption = "Entre 6 y 8"
Case 9 To 10 : lblSalida.Caption = "Entre 9 y 10"
Case Is >= 10 : lblSalida.Caption = "Mayor o igual a 10"
Case Else : lblSalida.Caption = "Negativo o 0"
End Select
Pg. 57
Pero podramos usar la instruccin Select Case de forma especial. Si ponemos la expresin a
evaluar como True y en las propiedades Checked de los controles como posibles valores, los if
anteriores se pueden reemplazar por:
Select Case True
Case rbtAndando.Checked : lblSeleccionado.Text = " rbtAndando" ' Si se ha
seleccionado le pone su nombre
Case rbtEnBici.Checked : lblSeleccionado.Text = " rbtEnBici"
Case rbtEnBus.Checked : lblSeleccionado.Text = " rbtEnBus"
Case rbtEnVehiculoPropio.Checked : lblSeleccionado.Text = "
rbtEnVehiculoPropio"
Case Else : lblSeleccionado.Text = "Ninguno" ' No hay ninguno seleccionado
End Select
Los bucles While...Wend se pueden anidar a cualquier nivel. Cada Wend coincide con el
While ms reciente.
Tambin tenemos los bucles Do..Loop con los 4 posibles formatos, que son ms completos
que el anterior (tienen la posibilidad de una salida alternativa con el Exit Do). En este caso las
instrucciones se repiten mientras la condicin sea cierta (While) o hasta que lo sea (Until). A
su vez, en ambos casos, tenemos 2 posibles formatos:
Do [{While | Until} condicin]
[instrucciones]
[Exit Do]
[instrucciones]
Loop
Do
[instrucciones]
[Exit Do]
[instrucciones]
Loop [{While | Until} condicin]
Pg. 58
Es decir, la condicin se puede poner arriba o abajo y en cualquiera de las formas: While o
Until.
Se puede utilizar cualquier nmero de instrucciones Exit Do ubicadas en cualquier lugar
dentro de una estructura de control DoLoop, para proporcionar una salida alternativa. La
instruccin Exit Do se utiliza frecuentemente en la evaluacin de alguna condicin, por ejemplo,
IfThen. En este caso, la instruccin Exit Do transfiere el control a la instruccin que sigue
inmediatamente a la instruccin Loop.
Cuando se utiliza con instrucciones anidadas DoLoop, la instruccin Exit Do transfiere
control al bucle que est anidado un nivel por encima del bucle donde ocurre.
Ejemplo:
Estos dos bucles son equivalentes (lo importante es donde se evala la condicin, el estilo
until o while depende ms del gusto personal):
Do
If n < 0 Then Exit Do ' Provoca otra posible salida del bucle
n = n + 1
Loop Until n > 10
Do
If n < 0 Then Exit Do ' Provoca otra posible salida del bucle
n = n + 1
Loop While n <= 10
Bucle For
Permite ejecutar un conjunto de instrucciones un nmero concreto de veces.
For contador = principio To fin [Step incremento]
[instrucciones]
[Exit For]
[instrucciones]
Next [contador]
El bucle finaliza cuando la condicin es > que el valor final (siempre que el incremento sea
positivo) o si es < que el valor final para incrementos negativos. Si no se especifica ningn
incremento, por defecto toma el valor.
En la parte del Next escribir o no el nombre del contador es simplemente para dar mayor
legibilidad a la instruccin, pero no le aporta nada.
Una vez que se inicia el bucle y se han ejecutado todas sus instrucciones, incremento se
suma a contador volviendo a evaluar si la variable contador ya es > que fin (o < para
incrementos negativos). Dependiendo de la respuesta las instrucciones se vuelven a ejecutar de
nuevo o se sale del bucle y la ejecucin contina con la instruccin siguiente a Next. Veamos
algunos ejemplos:
suma = 0 ' inicializamos el acumulador a 0
For i = 1 To 10 Step 2 ' cont toma valores 1,3,5...hasta 11 (11>10->se sale)
suma += i ' guarda en suma 1+3+5+7+9. Con el valor 11 se ha salido,
Next
Pg. 59
i,
Esta forma de declaracin puede ser muy prctica, siempre que la variable solo la usemos
para el bucle, y si es as y tenemos 2 For seguidos deberamos declararla ambas veces.
For i As Integer = 1 To 10 ' se declara para este For
'instrucciones a ejecutar 10 veces
Next
'En este espacio entre For no se reconoce ninguna variable i
For i As Integer = txtNum.Text To 15 ' Es una nueva i
'instrucciones a ejecutar varias veces, depender el valor que tenga txtNum
Next
Si sabemos que una variable solo la necesitamos en ese espacio es muy cmo declararla
dentro de la instruccin y sobretodo porque as optimizamos recursos.
Atencin: A partir de las ltimas versiones de Visual Basic.Net si usamos una variable no
declarada en un For, es lo mismo que si se declara en l, es decir, los bucles anteriores equivalen
a:
Pg. 60
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
' cdigo para trabajar con ficheros, etc.
Catch ex As System.IO.IOException
' el cdigo a ejecutar cuando se produzca ese error
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
' cdigo que queremos controlar
Catch ex As Exception ' ex es el nombre de la variable. Se puede cambiar
Pg. 61
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
' cdigo que queremos controlar
Catch
' el cdigo a ejecutar cuando se produzca cualquier error
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.
Pg. 62
Con este cdigo estamos indicndole al Visual Basic .NET que queremos "lanzar" (Throw)
una nueva excepcin (New Exception) y que el mensaje que se mostrar, ser el que le
indiquemos dentro de los parntesis.
Cuando nosotros lanzamos (o creamos) una excepcin, el error lo interceptar un bloque Try
que est activo, si no hay ningn bloque Try activo, ser el CLR (runtime de .NET Framework)
el que se encargar de interceptar esa excepcin, pero deteniendo la ejecucin del programa...
Private _fechaNacimiento As Date
''' <summary>
''' Permite modificar la fecha de nacimiento
''' </summary>
''' <value>Debe ser un valor no superior a la fecha actual. Si no lo es lanza una
excepcin</value>
''' <returns>Devuelve la fecha de nacimiento. Si no se ha introducido, lanza una
excepcin</returns>
''' <remarks></remarks>
Property FechaNacimiento As Date
Get ' Si _fechaNacimiento est "sin valor" lanza una excepcin
If _fechaNacimiento = #12:00:00 AM# Then Throw New Exception("Esta persona no
conoce su fecha de nacimiento")
Return _fechaNacimiento
End Get
Set(ByVal value As Date) ' Controla que sea inferior o igual a la fecha actual
If value > DateTime.Today Then Throw New Exception("La fecha de nacimiento
no puede ser superior a la actual")
_fechaNacimiento = value
End Set
End Property
Pg. 63
Atencin: Nunca deberamos usar un Try si tenemos otra forma ms sencilla y concreta de
resolver el control de la excepcin. En el ejemplo anterior controlar que en la caja de texto haya
un dato lgico (es decir, una fecha) se debera hacer en la forma:
If Not IsDate(txtFechaNacimiento.Text) Then
MessageBox.Show("No hay una fecha vlida", "Atencin")
txtFechaNacimiento.Clear()
txtFechaNacimiento.Focus()
Exit Sub
End If
Pg. 64
La primera cadena de caracteres del mensaje contiene el mensaje que indica al usuario o
usuaria el tipo de informacin que debe introducir; en el ejemplo Introduce el nombre de
usuario. Si el mensaje contiene varias lneas, debemos introducir explcitamente al final de cada
una de ellas un retorno de carro y avance de lnea, lo cual podemos hacerlo mediante la
constante CrLf de la clase ControlChars.
La funcin InputBox siempre devuelve un dato de tipo String.
El resto de los parmetros son opcionales. Si queremos omitir un argumento que precede a
otro especificado, deberemos poner las correspondientes comas delimitadoras.
Pg. 65
La cadena de caracteres ttulo ser visualizada en la barra de ttulo del dilogo; si se omite
como en el ejemplo anterior, se pone como ttulo el nombre de la aplicacin (en el ejemplo
Atencin).
La cadena de caracteres por_omisin especifica el texto que aparecer en la caja de texto; si
se omite, la caja de texto aparece vaca. (En el siguiente ejemplo la caja de texto aparecer por
defecto con la palabra Cuatrovientos)
nombre = InputBox("Nombre del instituto", "Introduce el dato", "Cuatrovientos")
Los argumentos posx y posy son las coordenadas x e y medidas desde la izquierda y parte
superior de la pantalla respectivamente, expresadas en twips (1 twip = 1/1440 pulgadas). Si se
omiten, la caja de dilogo se visualiza centrada horizontalmente y a 1/3 de la parte superior de la
pantalla.
Si al ejecutar el InputBox, el usuario o usuaria pulsa el botn de Aceptar, la funcin
InputBox devuelve el valor (string) que se encuentra en la caja de texto del InputBox. En el
ejemplo de la figura nombre recibira maria.
Por el contrario, si se pulsa el botn de Cancelar e independientemente del valor que
tengamos en la caja de texto, la funcin InputBox devuelve una cadena vaca.
Por tanto, si deseamos saber si el usuario/a ha pulsado Aceptar o Cancelar basta que
preguntemos por la variable recogida (en nuestro caso nombre) y ver si su valor es o no.
Como puedes suponer, no podemos distinguir si el usuario/a ha pulsado la tecla Cancelar o
Aceptar con la caja de texto vaca.
Ejemplo:
nombre = InputBox("Introduce el nombre de usuario" & ControlChars.CrLf & "Debe
ser uno existente", "Atencin")
If nombre = "" Then Exit Sub ' Si se ha pulsado Cancelar no se desea continuar
Pg. 66
Al igual que en el la ventana InputBox, si deseamos que el mensaje conste de varias lneas
deberemos indicarlo con la constante CrLf, Cr, Lf o NewLine de la clase ControlChars
MessageBox.Show("Cerrar programa" & ControlChars.CrLf & "Grabar datos?",
"Atencin!!!", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)
Como podemos comprobar, hay ventanas que solo sirven para dar informacin (mostrando el
botn Aceptar para cerrarla una vez leda), pero hay otras veces, como en el ejemplo de arriba,
en las que se presentan varios botones para realizar una accin diferente dependiendo del botn
pulsado por la o el usuario.
En ese caso, necesitaremos una variable del tipo DialogResult que es el devuelto por el
mtodo Show, que recoja la respuesta como vemos en el siguiente ejemplo:
Dim resp As DialogResult
resp = MessageBox.Show("Deseas continuar?", "Atencin", MessageBoxButtons.YesNo,
MessageBoxIcon.Question)
If resp = Windows.Forms.DialogResult.No Then Exit Sub ' Ha respondido que no
desea continuar
Hay ocasiones en las que no necesitamos guardarlo en una variable, sino simplemente
preguntar por la respuesta, en ese caso podemos hacerlo directamente en la forma:
If MessageBox.Show("Deseas continuar?", "Atencin", MessageBoxButtons.YesNo,
MessageBoxIcon.Question) = Windows.Forms.DialogResult.No Then Exit Sub ' Ha
respondido que no desea continuar
Pues esto ocasionara que se mostraran 3 ventanas seguidas, pues cada vez que escribimos
MessageBox.Show se muestra una diferente.
Pg. 67
Tipo
devuelto
CBool
Boolean
CByte
Byte
CChar
Char
CDate
Date
CDbl
Double
-1,79769313486232E308 a
-4,94065645841247E-324 para valores negativos; 4,94065645841247E-324
a 1,79769313486232E308 para valores positivos.
CDec
Decimal
CInt
Integer
CLng
Long
CObj
Object
CSByte
SByte
CShort
Short
CSng
Single
CStr
String
Los valores devueltos para CStr dependen del argumento expression. Mira
en la ayuda Valores devueltos para la funcin CStr..
CUInt
UInteger
CULng
ULong
CUShort
UShort
Nota. Si la expresin del argumento expresin que se pasa a la funcin est fuera del
intervalo del tipo de dato al que se va a convertir o no es numrico, se produce una excepcin
Pg. 68
Cuando la parte fraccionaria es exactamente 0,5, CByte, CInt y CLng siempre redondean al
nmero par ms cercano. Por ejemplo, 0,5 redondea a 0, y 1,5 redondea a 2.
Atencin Aunque en muchas no necesitemos hacer conversiones porque VB.Net lo hace de
forma automtica, hay otras en que l mismo nos lo exigir.
Dim num As Byte = txtNum.Text ' Si en la caja de texto hay un valor entre 0 y 255
hace intrnsecamente la conversin.
Clase Convert
Si queremos hacerlo con POO, podemos usar la clase Convert, pero teniendo en cuenta que
esta clase trabaja con los tipos de la plataforma, de tal forma, que si queremos hablar, por
ejemplo del tipo Integer de VB debemos hacer referencia a System.Int32 de la plataforma.
Los mtodos son del tipo ToBoolean, ToInt32, ...
Dim num As Integer =
Convert.ToInt32(txtNumero.Text)
Int y Fix
Las funciones Int y Fix sirven para truncar un nmero, es decir, quitan la parte fraccionaria
del nmero pasado como parmetro y devuelven el valor entero resultante.
La diferencia entre las funciones Int y Fix es que si el nmero es negativo, Int devuelve el
primer entero negativo menor o igual que el nmero, mientras que Fix devuelve el primer entero
negativo mayor o igual que el nmero. Observa los siguientes ejemplos:
Dim numInt As Decimal = Int(txtNum.Text) ' Si txtNumText vale -7,2 recoge -8,
con 7,2 o 7,8 valdr 7
Dim numFix As Decimal = Fix(txtNum.Text) ' Con -7,2 recoge -7, con 7,2 o 7,8
valdr 7
Dim numCInt As Integer = CInt(txtNum.Text) ' Con -7,2 o 7,2 coge -7, con -7,8
guarda -8 y 8 si el valor es 7,8
Constantes Pi y E
Representan a las constantes y e respectivamente. Es decir, son equivalentes a los valores
3.14926535897931 y 2.7182818284590451.
Pg. 69
Son muy sencillas de utilizar, basta con poner el nombre de la constante indicando que es de
la clase Math en la forma:
lblArea.Text = Math.Pi * txtRadio.Text ^ 2 ' Hay que especificar que PI es
miembro de Math
Floor y Ceiling
Devuelve el nmero entero ms grande menor o igual que el nmero especificado y
Devuelve el nmero entero ms pequeo mayor o igual que el nmero especificado.
Para verlo, supongamos el siguiente ejemplo:
Dim numF As Integer = Math.Floor(CDec(txtNum.Text))
Dim numC As Integer = Math.Ceiling(CDec(txtNum.Text))
Los posibles valores de numF y numC dependiendo del valor de txtNum seran:
txtNum.Text
numF
numC
1,2
-1,2
-2
-1
1,8
-1,8
-2
-1
Sqrt
Devuelve la raz cuadrada del valor pasado como parmetro. Veamos un ejemplo del uso de
esta funcin
Private Sub btnRaiz_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnRaiz.Click
lblRaiz.Text = Math.Sqrt(txtNum.Text)
End Sub
Pg. 70
Si queremos mostrar un mensaje especial, diferente de NeuN (que es una palabra muy
extraa para cualquier usuari@ deberemos controlar primero que el resultado sea vlido, lo cual
lo podemos hacer gracias al mtodo IsNaN del tipo Double. Observa el mensaje del siguiente
ejemplo.
Lgicamente en este caso concreto tenemos otra solucin an ms sencilla, que es preguntar
si el valor de la caja de texto es negativo:
If txtNum.Text < 0 Then
lblResultado.Text = "Error, no puede ser negativo"
Else
lblResultado.Text = Math.Sqrt(txtNum.Text)
End If
Abs
Devuelve el valor absoluto de un nmero.
Veamos un ejemplo:
Dim num As Decimal = -7.8
Pg. 71
Log(Double, Double) : Devuelve el logaritmo del primer parmetro en la base del segundo.
Dim numLogBase As Decimal = Math.Log(txtNum.Text, txtBase.Text) ' Devuelve el
logaritmo en base txtBase.Text del nmero que est en txtNum
Exp
Devuelve e elevado a la potencia especificada. Esta funcin es la inversa a Log. Si el nmero
pasado como parmetro es igual a NaN o PositiveInfinity, devuelve ese valor, mientras que si es
igual a NegativeInfinity, devuelve 0.
Dim num As Double = Math.Exp(txtNum.Text) ' Devuelve etxtNum.Text
Pg. 72
Fechas
Para declarar una variable fecha tenemos varias posibilidades. En nuestro caso lo haremos
con alguna de las siguientes formas (es decir usando o no constructor y en este ltimo caso con
valor inicial por defecto o pasndole un valor existente).
Generalmente lo vamos a hacer:
Private fecha As Date ' Inicialmente vale #12:00:00 AM#, que es el valor por
defecto
Private ComienzoSigloXXI As New Date(2000, 1, 1, 0, 0, 1) ' Comienza en la hora
0:0:1 del da 1/1/2000
Private fechaAct As Date = Today ' Se guarda solo la fecha actual, h:m:s se
quedan a 0
Private fechaHoraAct As Date = Now ' En este caso recibe la fecha actual y hora
del sistema
Pg. 73
Te marco en negrita las que ms vamos a utilizar, por ser ms tiles o porque no se
encuentran como miembros de los datos de tipo fecha.
Propiedades
Nombre
Now
Descripcin
Devuelve un valor de Date que contiene la fecha y la hora actuales segn el sistema.
TimeOfDay Devuelve o establece un valor de Date que contiene la hora actual del da segn el sistema.
Today
Devuelve o establece un valor de Date que contiene la fecha actual segn el sistema.
Mtodos
Nombre
Descripcin
DateAdd
Devuelve un valor de Date que contiene un valor de fecha y hora al que se ha sumado
un intervalo de tiempo especificado.
DateDiff
Devuelve un valor Long que especifica el nmero de intervalos de tiempo entre dos
valores de Date.
DatePart
Day
Hour
Devuelve un valor de tipo Integer del 0 al 23 que representa la hora del da.
Minute
Month
Devuelve un valor de tipo Integer del 1 al 12 que representa el mes del ao.
MonthName
Devuelve un valor de tipo String que contiene el nombre del mes especificado.
Second
Devuelve un valor de tipo Integer del 0 al 59 que representa el segundo del minuto.
DateSerial
TimeSerial
TimeValue
Devuelve un valor de Date que contiene la informacin de hora representada por una
cadena, con la informacin de fecha establecida en el 1 de enero del ao 1.
Weekday
Year
Pg. 74
Descripcin
AddDays
Devuelve un nuevo objeto DateTime que suma el nmero especificado de das al valor
de esta instancia.
AddHours
AddMilliseconds
AddMinutes
AddMonths
AddSeconds
AddTicks
AddYears
Devuelve un nuevo objeto DateTime que suma el nmero especificado de aos al valor
de esta instancia.
DaysInMonth
IsLeapYear
Subtract
Para ver estas funciones y/o mtodos observa el siguiente ejemplo. Supongamos que
tenemos un formulario en el que tras comprobar que hay una fecha y un nmero en las dos cajas
de texto de arriba, muestra la fecha resultante de sumar a la fecha inicial los aos indicados. En
el caso del da de la semana y del mes se indicar en nmero y nombre.
Pg. 75
Nota. Podemos generar una variable de fecha introduciendo hora, minutos y segundos como
mostramos a continuacin y ver tambin la diferencia de dos fechas en la forma:
Dim fNac As Date = New System.Date(1980, 8, 10, 6, 0, 0) ' Ao, Mes, Dia, Hora,
Minutos y Seg
lblHoraNac.Text = fNac.Hour ' Escribe el nombre del mes y la hora
Dim vivido As TimeSpan = Now.Subtract(fNac)
Dim minViv As Integer = vivido.TotalMinutes ' Now.Subtract(fNac).TotalMinutes
Pg. 76
String.Compare
Sirve para comparar dos cadenas, devolviendo un valor -1,0 o 1 dependiendo de que la
primera sea alfanumricamente menor, igual o mayor que la segunda. La usaremos cuando
deseamos considerar que maysculas y minsculas se consideren iguales.
Ejemplo:
If String.Compare("qu", "Qu", True) = 0 Then
MessageBox.Show("Son iguales") 'En este caso son iguales, pero con False como
ltimo parmetro habra considerado que son distintas
Else
MessageBox.Show("Son distintas")
End If
Pg. 77
Veamos como en el caso anterior los mtodos que ms vamos a utilizar en el caso de las
variables de tipo String. Si necesitas otros puedes acceder a la ayuda de VStudio.
Nombre
Descripcin
Contains
Devuelve un valor que indica si el objeto String especificado aparece dentro de esta
cadena.
EndsWith
IndexOf
Insert
Replace
Devuelve una nueva cadena en la que todas las apariciones de una cadena especificada en
la instancia actual se reemplazan por otra cadena especificada.
Split
Devuelve una matriz de cadenas que contiene las subcadenas de esta instancia que estn
delimitadas por elementos de la matriz de caracteres Unicode especificada. Se puede
especificar mediante un parmetro el nmero mximo de subcadenas que se van a
devolver.
StartsWith
Substring
ToLower
ToUpper
Trim
Quita todos los caracteres de espacio en blanco del principio y el final del String actual.
Y las propiedades:
Nombre
Descripcin
Chars
Obtiene el carcter situado en una posicin de carcter especificada en el objeto String actual.
Length
Pg. 78
Descripcin
Devuelve un nmero aleatorio entero no negativo.
Next(Int32)
Rellena con nmeros aleatorios los elementos de una matriz de bytes especificada.
NextDouble
Como ves, tenemos el mtodo Next sobrecargado, para pedir que nos genere un n aleatorio
sin ms, menor que un valor dado o dentro de un rango definido.
Ejemplo:
Pg. 79
Pg. 80
Pg. 81
Descripcin
Public
Private
Protected, Friend y
Protected Friend
Funciones (Function)
Una funcin es un procedimiento que cuando se ejecuta devuelve un resultado.
Y una segunda, que dados dos nmeros devuelva el cociente de la divisin entera como
resultado de una funcin y el resto mediante un parmetro de salida.
Pg. 82
mbito: Como ya hemos dicho, define el lugar desde el que se puede acceder a la
funcin y para empezar vemos el mbito Private (solo desde el formulario, mdulo o
clase que lo define) y Public para que pueda acceder a l desde cualquier lugar de la
aplicacin.
Public Function DivisionEntera(ByVal dividendo As Integer, ByVal divisor As
Integer, ByRef resto As Integer) As Decimal
Private Function Area(ByVal radio As Decimal) As Decimal
Pg. 83
Como puedes apreciar en los ejemplos, siempre haremos algo con el resultado de la funcin,
o bien asignaremos a una variable, al texto de un control, mostrarlo en un MessageBox o lo que
necesitemos en el momento.
Procedimientos (Sub)
Sintaxis que define un procedimiento Sub
[Ambito] Sub Nombre_Procedimiento [(Lista de parmetros)]
Instrucciones del Sub pudiendo incluir una o varias instruccin Exit Sub
End Sub
La explicacin es anloga a la dada para las funciones.
Veamos un ejemplo:
Public Sub MostrarHora(ByVal seg As Integer)
Dim hora As Date
hora = DateAndTime.TimeOfDay.AddSeconds(seg)
MessageBox.Show("Dentro de " & seg & " segundos sern las " & hora)
End Sub
Pg. 84
Declarar argumentos
Declaramos cada argumento de un procedimiento del mismo modo en que declaramos una
variable, especificando el nombre del argumento y el tipo de datos. Observa que incluso los
procedimientos orientados a eventos tienen dos argumentos que son definidos por valor.
Private Function Area(ByVal radio As Decimal) As Decimal
Public Function DivisionEntera(ByVal dividendo As Integer, ByVal divisor As
Integer, ByRef resto As Integer) As Decimal
Public Sub MostrarHora(ByVal seg As Integer)
Private Sub frmBanco_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Pg. 85
Memoria
numero
5
Llamada
Triple(numero)
num
5
15
Declaracin de la funcin
Triple(ByVal num )
Si hacemos las mismas llamadas nos encontraremos con algunos cambios tal vez no
previstos:
Dim numero As Integer = 5
Dim tri As Integer = Triple(numero)
MessageBox.Show("El triple del nmero " & numero & " es " & tri &
ControlChars.CrLf & "Y el triple de 3 es " & Triple(3)) ' En este caso la
variable numero cambia el valor, el 3 al ser un valor constante lgicamente no
puede cambiar
En este caso habramos mostrado una ventana como la que vemos a continuacin:
Lo que ocurre en el fuente anterior a nivel de gestin interna en memoria de los parmetros
es lo siguiente: cuando se realiza la llamada al procedimiento y se pasa el parmetro, el entorno
detecta que se trata de un parmetro pasado por referencia, y tanto la variable del cdigo
llamador como la del procedimiento llamado utilizan la misma direccin de memoria o
referencia hacia los datos, por lo que los cambios realizados en un procedimiento afectarn
tambin al otro. La siguiente figura muestra una representacin grfica de este proceso.
Memoria
num / numero
5
15
Llamada
Triple(numero)
Declaracin de la funcin
Triple(ByRef num )
Pg. 87
Explicacin
Implicaciones
Ventaja
Por valor:
ByVal
El procedimiento
invocado recibe una
copia de los datos
cuando es invocado
Si el procedimiento invocado
modifica la copia, el valor
original de la variable
permanece intacto. Cuando la
ejecucin retorna al
procedimiento de llamada, la
variable contiene el mismo valor
que tena antes de que el valor se
pasara.
Protege la variable de
ser cambiada por el
procedimiento
invocado.
Por
referencia:
ByRef
El procedimiento
invocado recibe una
referencia a los
datos originales (la
direccin de los
datos en memoria)
cuando es invocado.
El procedimiento invocado
puede modificar la variable
directamente. Cuando la
ejecucin retorna al
procedimiento de llamada, la
variable contiene el valor
modificado.
El procedimiento
invocado puede
utilizar el argumento
para devolver un
nuevo valor al cdigo
de llamada.
Pg. 88
Pg. 89
Pg. 90
Objeto
Un objeto es una agrupacin de cdigo, compuesta de propiedades y mtodos, que pueden
ser manipulados como una entidad independiente. Las propiedades definen los datos o
informacin del objeto, permitiendo consultar o modificar su estado; mientras que los mtodos
son las rutinas que definen su comportamiento.
Un objeto es una pieza que se ocupa de desempear un trabajo concreto dentro de una
estructura organizativa de nivel superior, formada por mltiples objetos, cada uno de los cuales
ejerce la tarea particular para la que ha sido diseado.
Clase
Una clase no es otra cosa que el conjunto de especificaciones o normas que definen cmo
va a ser creado un objeto de un tipo determinado; algo parecido a un manual de instrucciones
conteniendo las indicaciones para crear el objeto.
Los trminos objeto y clase son utilizados en OOP con gran profusin y en contextos muy
similares, por lo que para intentar aclarar en lo posible ambos conceptos, diremos que una clase
constituye la representacin abstracta de algo, mientras que un objeto constituye la
representacin concreta de lo que una clase define. Ejemplo, cuando decimos la palabra Coche
nos hacemos una imagen mental de lo que ese concepto significa y las acciones que puede
realizar, pero el objeto real es cuando hablamos de un coche concreto (ejemplo miCoche).
De la misma forma, conocemos la clase TextBox, Label, y los objetos txtNombre,
txtDireccin, lblResultados, .
Es decir, una clase que describe los objetos que de ella se pueden crear, tiene propiedades
que describen sus atributos, mtodos que definen sus acciones y eventos que definen sus
respuestas y que por tanto se pasarn a todas las instancias de esa clase.
Nota. Recuerda que, en realidad desde el comienzo, en todos nuestros proyectos tenemos
como mnimo definida una clase, la del formulario.
Es decir, cada vez que creamos (con el diseador) un nuevo formulario estamos creando una
clase cuyo nombre es el elegido para el formulario (si no lo cambiamos por defecto habra sido
Form1). El objeto ser luego el formulario que aparece en pantalla cuando ejecutemos el
programa y que tiene un comportamiento definido en la clase.
Pg. 91
Creando la clase
Para crear una nueva clase en VB.Net podrs hacerlo desde el men Proyecto -> Crear clase
o en el Explorador de Soluciones eligiendo el proyecto con el botn secundario del ratn para ir
a Agregar ->Clase como puedes apreciar en las siguientes figuras:
Pg. 92
Es decir, ya tenemos creada una nueva clase, an sin ninguna propiedad y con una serie de
mtodos aparentemente ocultos que tiene toda clase en VS.Net solo por el hecho de ser creada.
En realidad estos mtodos vienen definidos en la super clase Object de la cual hereda toda clase,
pero estos conceptos los dejaremos para ms adelante.
Estos mtodos iniciales los puedes apreciar en cuanto declares una variable de esta clase (un
objeto de esta clase), como se muestra en la siguiente figura:
Miembros de la clase
Los elementos de una clase que contienen sus datos y definen su comportamiento, es decir,
las propiedades y mtodos, reciben adems el nombre de miembros de la clase, trmino que
tambin venimos utilizando en repetidas ocasiones.
Propiedades
Una propiedad en la clase se define, por norma general (aunque haya casos en los que no sea
as), mediante dos elementos: una variable propiedad y un procedimiento que define a la
propiedad.
La variable de propiedad, tal y como su nombre indica, es una variable con mbito privado
a nivel de la clase, que se encarga de guardar el valor de la propiedad. Por su parte el
procedimiento de propiedad o Property, es el encargado de actuar de puente entre el cdigo
cliente y la variable de propiedad, realizando las operaciones de acceso y asignacin de valores
a dicha variable.
Por lo tanto, para crear una propiedad en nuestra clase, generalmente primero declararemos
una variable Private, y en segundo lugar un procedimiento de tipo Property, que consta de dos
bloques: Get, para devolver el valor de la variable de propiedad; y Set, para asignrselo.
Cuando declaramos un procedimiento Property, debemos, al igual que en una funcin,
tipificarlo (definirle el tipo al que pertenece), ya que una de sus labores consiste en la
devolucin de un valor.
Para devolver el valor, en el bloque Get utilizaremos la palabra clave Return, seguida del
valor de retorno.
Pg. 93
En cuanto a la asignacin de valor, el bloque Set utiliza un parmetro con el nombre Value,
que contiene el valor para asignar a la propiedad.
Si seguimos con nuestra clase CuentaBancaria, recordaremos que tenamos las propiedades
NumCuenta, Titular y Saldo.
Observacin. En la declaracin de las clases seguimos con la notacin Camel, en la
siguiente forma: Para nombrar a la clase, propiedades, mtodos (y eventos si los hubiera)
comenzando con la primera letra en maysculas (ejemplo: clase CuentaBancaria, propiedad
NumCuenta), para las variables privadas o parmetros (value, cantidad) comenzando en
minsculas y en el caso de las variables propiedad (las que contienen el valor de la propiedad)
con el mismo nombre que la propiedad precedido del guin bajo: _Titular.
Public Class CuentaBancaria ' Nombre de la clase (empieza en May)
Private _Titular As String ' variable privada que va a contener el nombre de la
persona titular de la cuenta. Se llama igual que la propiedad pero con el _
Public Property Titular As String ' Definicin de la propiedad. El nombre en May
Get ' Se ejecuta cuando desde "el programa" se pregunta por el/la Titular
Return _Titular
' Devuelve el valor que tiene en la variable
End Get
Set(ByVal value As String) ' Se ejecuta cuando desde "el programa" se intenta
modificar al/a Titular con el valor que viene en la variable value. Este nombre
comienza en min
_Titular = value
' Modificaremos el valor de la variable para que recoja
el nuevo valor que viene en la variable value
End Set
End Property
End Class
Observacin: Te has dado cuenta que la variable de la propiedad y la propiedad son del
mismo tipo String? Esto es lgico y obligatorio, ya que si la variable contiene el valor de la
propiedad deber ser de ese tipo. No podramos decir que Titular es String y que _Titular es
Decimal.
De la misma forma empezaramos a declarar las propiedades NumCuenta y Saldo, pero antes
debemos hacernos la siguiente consideracin. As como el nombre de la persona titular de la
cuenta puede cambiar en cualquier momento, se puede cambiar el nmero de cuenta o la fecha
de edicin una vez creada? De la misma forma, podemos ir a la caja de ahorros o banco y
decirles que modifique nuestro Saldo sin hacer la operacin de Ingresar o Retirar dinero? Es
evidente que no. As pues en este ejemplo nos encontramos con 2 propiedades que necesitamos
definir como especiales, es decir, que se pueden leer (podemos preguntar por el Saldo o por el
NumCuenta) pero no modificar. Nos encontramos con las llamadas Propiedades de Solo
Lectura, que en el caso de VB.Net se declaran ReadOnly.
Cmo las definiramos en este caso?
Public Class CuentaBancaria
' Variables privadas. Contienen el valor de las propiedades de nombre semejante
Private _Titular As String
Private _Saldo As Decimal
Private _NumCuenta As Decimal
Private _FechaEdicion As Date
Public Property Titular As String
Escritura
' Definicin anterior
End Property
Pg. 94
Nota: De la misma forma que podemos definir una propiedad de slo lectura, tambin
podemos crear una propiedad de Slo Escritura (WriteOnly) es decir, una propiedad que slo
aceptar que se asignen nuevos valores, pero que no permitan obtener el valor que tienen... La
verdad es que este tipo de propiedades no son muy habituales, pero podemos hacerlo.
Veamos cmo tendramos que declarar una propiedad de slo escritura. Para ello vamos a
suponer (lo cual no es muy lgico) que tuvisemos una
' Supongamos que tuvisemos una propiedad Interes que se pueda modificar desde el
exterior ("por programa" o desde otra clase) pero que no se pueda leer (Es decir,
el programa o la otra clase no puedever el contenido de Interes)
Private _Interes As Decimal
Public WriteOnly Property Interes As Decimal ' Propiedad de solo escritura.
Set(ByVal value As Decimal) ' Solo tiene la parte del Set
_Interes = value
End Set
End Property
Mtodos
Adems de las propiedades vistas, habamos dicho que en una cuenta podamos Ingresar y
Retirar dinero y preguntar la Antigedad de la cuenta. Esto significa que tenemos que definir un
mtodo para cada accin.
Los mtodos estn definidos mediante subprogramas o funciones, que a su vez pueden tener
o no parmetros. Hemos elegido estos mtodos para tener una representacin de ambos casos.
Pensemos en la forma de definirlos. En los casos de Ingresar y Retirar, deberemos indicar la
cantidad con la que deseamos realizar la operacin, sabiendo que el Saldo sufrir una
modificacin.
As pues estos dos mtodos tendran una declaracin del tipo:
Public Sub Ingresar(ByVal cantidad As Decimal) ' Declaramos el mtodo Ingresar.
Necesita recibir como dato la cantidad de dinero a ingresar
_Saldo = _Saldo + cantidad ' Modificamos el valor de la variable que contiene
el Saldo. Esta instruccin es equivalente a _Saldo += cantidad
' Generalmente pondremos la propiedad en lugar de la variable, pero eso ser
cuando la propiedad no sea ReadOnly y se controle el dato que recibe
End Sub
Pero ojo!, en el caso de Retirar dinero deberemos tener en cuenta que no podemos retirar
una cantidad superior al saldo existente. Es por eso que definiremos este mtodo en la forma:
Public Sub Retirar(ByVal cantidad As Decimal)
If cantidad <= _Saldo Then _Saldo = _Saldo - cantidad ' Solo modificamos el
valor del Saldo si hay suficiente
End Sub
Pg. 95
programa se har alguna forma, pero en general podemos decir que nunca ser mediante un
MessageBox!!!!
Lo normal en este caso sera provocar una excepcin, pero esto lo veremos ms adelante. Otra
posibilidad sera que en lugar de un Sub fuese una funcin y devolviese la cantidad retirada, en
la forma:
Public Function Retirar(ByVal cantidad As Decimal) As Decimal ' Devuelve la
cantidad realmente retirada
If cantidad <= _Saldo Then
_Saldo = _Saldo - cantidad ' Solo modificamos el valor del Saldo si hay
suficiente
Return cantidad ' Hemos retirado esta cantidad del saldo
End If
Return 0 ' No se ha retirado nada, ya que no ha entrado en el If
End Function
Pg. 96
Para que una variable de este tipo realmente referencie a un objeto real tenemos dos
posibilidades:
Crendolo mediante el operador New.
miCuenta = New CuentaBancaria ' Crea un nuevo objeto de esta clase, con los
valores iniciales en sus propiedades.
Crear un objeto significa reservar un nuevo espacio en memoria para sus atributos.
Haciendo referencia a otro objeto ya existente.
Dim otraCuenta As CuentaBancaria
otraCuenta = miCuenta
miCuenta
otraCuenta
_FechaInicio: 10/12/2011
_Saldo: 3500
_Titular: 1DAM
_NumCuenta: 30350058215421254589
Ingresar
Retirar
Antiguedad
Pg. 97
En este caso escribira 1DAM ya que miTitular se ha quedado con el valor que tena.
Una vez creado un objeto, podremos utilizar sus propiedades y/o mtodos, como vemos en la
siguiente imagen.
Atencin. Aunque las propiedades y/o mtodos los saque solo por tener declarada la
variable, si hacemos referencia a una propiedad sin haber creado (New) o referenciado a un
objeto mediante una asignacin como en el caso anterior, la instruccin dara error de
ejecucin., como puedes ver en la siguiente imagen. Observa que miCuenta sala subrayada en
verde.
Pg. 98
Recordemos que el Saldo solo se poda modificar gracias a los mtodos Ingresar o Retirar.
Veamos su uso:
Private Sub btnIngresar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnIngresar.Click
If Not IsNumeric(txtCantidad.Text) Then Exit Sub
MessageBox.Show("Saldo actual " & miCuenta.Saldo, "Atencin")
miCuenta.Ingresar(txtCantidad.Text) ' Invoca al mtodo Ingresar del objeto
MessageBox.Show("El nuevo saldo es " & miCuenta.Saldo, "Atencin")
End Sub
Con los 2 MessageBox mostrando el Saldo de esa cuenta, conseguiramos ver el que tena
antes de ingresar esa cantidad y el que le queda tras hacerlo.
Recuerda que no habramos podido hacer la siguiente instruccin por ser una propiedad de
solo lectura, es decir, no se permite modificar desde el exterior de la clase.
miCuenta.Saldo = miCuenta.Saldo + txtCantidad.Text
propiedad ReadOnly
Mtodos constructores
El primer mtodo que es ejecutado al instanciar un objeto de la clase se denomina
constructor. Este tipo de mtodo resulta til para tareas de configuracin iniciales sobre el
objeto.
No es necesario escribir un mtodo constructor en la clase, ya que en el caso de que no
exista, el compilador se encarga de crearlo implcitamente. Es decir, tras construirse el objeto,
qu valor tienen sus propiedades por defecto? Pues como estamos en el lenguaje VB y este
inicializa las variables con unos valores concretos, esta ser la lgica que se mantendr.
Si continuamos con el ejemplo que llevamos de nuestra CuentaBancaria, qu ocurre con las
propiedades antes de asignarle ningn valor?
Dim otraCuenta As New CuentaBancaria
MessageBox.Show("Titular :" & miCuenta.Titular & ControlChars.CrLf & "Saldo " &
miCuenta.Saldo) ' Qu valores mostrara este MessageBox?
Pues, como no hemos definido ningn constructor y Titular es String, devolvera el valor
y en el caso del Saldo que es numrico el valor 0.
Hay otras ocasiones en las que queremos que al construirse el objeto comience con otros
valores diferentes. En ese caso necesitaremos escribir nuestros propio constructor o
constructores, mediante un mtodo especial llamado New().
Siguiendo con nuestro ejemplo cundo coge valor la propiedades FechaEdicion y
NumCuenta? Pues este sera el sitio lgico. Fjate especialmente en el caso de la fecha de
edicin, porque la solucin para el NumCuenta an es un poco complicado
Lo que est claro es que este sera el lugar ms lgico, en el momento en que se crea.
Pg. 99
As, cuando en otra parte del programa ejecutemos una instruccin del tipo:
miCuenta = New CuentaBancaria
o bien
Private miCuenta As New CuentaBancaria
Para conseguir que al crear un objeto utilice estos constructores deberamos hacer:
Dim oCuenta As CuentaBancaria
oCuenta = New CuentaBancaria() ' Utiliza el constructor sin parmetros, se crear
una nueva cuenta con el n que le corresponde y la fecha del sistema
oCuenta = New CuentaBancaria(txtTitular.Text) ' Utiliza el constructor con 1
parmetro, el n de cuenta ser el pasado en el parmetro
oCuenta = New CuentaBancaria(txtTitular.Text, txtCantidad.Text) ' Utiliza el 3,
creando la cuenta con estos valores para NumCuenta y FechaEdicion
Pg. 100
Pg. 101
Abstraccin
La abstraccin es aquella caracterstica que nos permite identificar un objeto a travs de sus
aspectos conceptuales.
Las propiedades de los objetos de una misma clase, pueden hacerlos tan distintos que sea
difcil reconocer que pertenecen a una clase idntica. No obstante, nosotros reconocemos a qu
clase pertenecen, identificando adems, si se trata de la misma clase para ambos. Ello es posible
gracias a la abstraccin.
Tomemos como ejemplo dos objetos coche, uno deportivo y otro familiar; su aspecto
exterior es muy diferente, sin embargo, cuando pensamos en cualquiera de ellos, sabemos que
ambos pertenecen a la clase Coche, porque realizamos una abstraccin o identificacin mental
de los elementos comunes que ambos tienen (ruedas, volante, motor, puertas, etc.).
Del mismo modo que hacemos al identificar objetos reales, la abstraccin nos ayuda a la
hora de desarrollar una aplicacin, permitindonos identificar los objetos que van a formar parte
Pg. 102
Encapsulacin
La encapsulacin establece la separacin entre el interfaz del objeto y su implementacin,
aportndonos dos ventajas fundamentales.
Por una parte proporciona seguridad al cdigo de la clase, evitando accesos y
modificaciones no deseadas; una clase bien encapsulada no debe permitir la modificacin
directa de una variable, ni ejecutar mtodos que sean de uso interno para la clase.
Por otro lado la encapsulacin simplifica la utilizacin de los objetos, ya que un programador
que use un objeto, si este est bien diseado y su cdigo correctamente escrito, no necesitar
conocer los detalles de su implementacin, se limitar a utilizarlo.
Tomando un ejemplo real, cuando nosotros utilizamos un objeto Coche, al presionar el
acelerador, no necesitamos conocer la mecnica interna que hace moverse al coche, sabemos
que el mtodo Acelerar del coche es lo que tenemos que utilizar para desplazarnos, y
simplemente lo usamos.
Pasando a un ejemplo en programacin, si estamos creando un programa de gestin y nos
proporcionan un objeto Cliente que tiene el mtodo Alta, y sirve para aadir nuevos clientes a
la base de datos, no precisamos conocer el cdigo que contiene dicho mtodo, simplemente lo
ejecutamos y damos de alta a los clientes en nuestra aplicacin.
Polimorfismo
El polimorfismo determina que el mismo nombre de mtodo, realizar diferentes acciones
segn el objeto sobre el que sea aplicado. Al igual que suceda en la encapsulacin, el
programador que haga uso del objeto, no necesita conocer los detalles de implementacin de los
mtodos, se limita a utilizarlos.
Pasando a un ejemplo real, tomamos dos objetos: Pelota y VasoCristal; si ejecutamos sobre
ambos el mtodo Tirar, el resultado en ambos casos ser muy diferente; mientras que el objeto
Pelota rebotar al llegar al suelo, el objeto VasoCristal se romper.
En un ejemplo aplicado a la programacin, supongamos que disponemos de los objetos
Ventana y Fichero; si ejecutamos sobre ambos el mtodo Abrir, el resultado en Ventana ser la
visualizacin de una ventana en el monitor del usuario; mientras que en el objeto Fichero, se
tomar un fichero en el equipo del usuario y se dejar listo para realizar sobre l operaciones de
lectura o escritura.
Herencia
Se trata de la caracterstica ms importante de la OOP, y establece que partiendo de una
clase a la que denominamos clase base, padre o superclase, creamos una nueva clase
denominada clase derivada, hija, o subclase. En esta clase derivada dispondremos de todo el
cdigo de la clase base, ms el nuevo cdigo propio de la clase hija, que escribamos para
extender sus funcionalidades.
A su vez podemos tomar una clase derivada, creando una nueva subclase a partir de ella, y
as sucesivamente, componiendo lo que se denomina una jerarqua de clases, que explicaremos
seguidamente.
Pg. 103
Existen dos tipos de herencia: simple y mltiple. La herencia simple es aquella en la que
creamos una clase derivada a partir de una sola clase base, mientras que la herencia mltiple nos
permite crear una clase derivada a partir de varias clases base. El entorno de .NET Framework
slo permite utilizar herencia simple.
Como ejemplo real de herencia, podemos usar la clase Coche como clase base; en ella
reconocemos una serie de propiedades como Motor, Ruedas, Volante, etc., y unos mtodos
como Arrancar, Acelerar, Frenar, etc. Como clase derivada creamos CocheDeportivo, en la
cual, adems de todas las caractersticas mencionadas para la clase Coche, encontramos
propiedades y comportamiento especficos como ABS, Turbo, etc.
Un ejemplo basado en programacin consistira en disponer de la una clase Empleado. Esta
clase se ocupara de las operaciones de alta de emplead@s, pago de nminas, etc.; pero en
un momento dado, surge la necesidad de realizar pagos a emplead@s que no trabajan en la
central de la empresa, ya que se trata de comerciales que pasan la mayor parte del tiempo
desplazndose. Para realizar dichos pagos usaremos Internet, necesitando el nmero de tarjeta
de crdito y la direccin email del empleado o empleada. Resolveremos esta situacin creando
la clase derivada CiberEmpleado, que hereda de la clase Empleado, en la que slo tendramos
que aadir las nuevas propiedades y mtodos para las transacciones electrnicas, puesto que las
operaciones tradicionales ya las tendramos disponibles por el mero hecho de haber heredado de
Empleado.
Jerarquas de clases
Como decamos en un apartado anterior, uno de los fines de la OOP consiste en la
clasificacin del cdigo; para ello se emplean jerarquas o rboles de clases, en los que a base de
niveles, se muestra un conjunto de clases conectadas por una relacin de herencia. Observemos
el esquema de la siguiente figura, en el que se muestra un ejemplo de la jerarqua de clases de
medios de transporte.
En esta representacin de ejemplo, como nivel superior de la jerarqua o clase base estara
Medios de transporte, de la que se derivaran las clases Barco, Tren, Automvil, y a su vez, de
estas ltimas, partiran nuevas clases hijas.
Pg. 104
Herencia
Como acabamos de describir en el apartado sobre caractersticas de la OOP, cuando a partir
de una clase existente, creamos una nueva clase derivada, esta nueva clase dispone de todas las
propiedades y mtodos de la clase base, ms el cdigo propio que implemente. Para reconocer si
existe esta relacin entre dos objetos, debemos realizar un anlisis sintctico sobre la misma
usando la partcula es un.
Tomando como ejemplo los objetos Empleado, CiberEmpleado y Factura, podemos decir
que s hay una relacin de herencia entre Empleado y CiberEmpleado, ya que al analizar la
frase Un objeto CiberEmpleado es un Empleado, el resultado es verdadero. No ocurre lo
mismo entre los objetos CiberEmpleado y Factura, ya que el anlisis de la frase Un objeto
CiberEmpleado es una Factura, devuelve falso.
Pertenencia
Los objetos pueden estar formados a su vez por otros objetos. Un objeto Factura puede estar
compuesto por objetos CabeceraFactura, LineaFactura, etc. Se dice en este caso que hay una
relacin de pertenencia, puesto que existe un conjunto de objetos que pertenecen a otro objeto o
se unen para formar otro objeto. A este tipo de relacin se le denomina tambin Contenedora.
Para reconocer si existe esta relacin entre dos objetos, debemos realizar un anlisis
sintctico sobre la misma usando la partcula tiene un. As, por ejemplo, la frase Un objeto
Factura tiene un objeto LineaFactura devolvera verdadero.
Utilizacin
Hay situaciones en que un objeto utiliza a otro para realizar una determinada tarea, sin
que ello suponga la existencia de una relacin de pertenencia entre dichos objetos.
Por ejemplo, un objeto Ventana puede utilizar un objeto Empleado para mostrar al usuario
las propiedades del empleado, sin necesidad de que el objeto Empleado sea propiedad del objeto
Ventana.
Ntese la importante diferencia entre esta relacin y la anterior, ya que aqu, el objeto
Ventana a travs de cdigo, crear, o le ser pasado como parmetro, un objeto Empleado, para
poder mostrarlo en el rea de la ventana.
Para reconocer si existe esta relacin entre dos objetos, debemos realizar un anlisis
sintctico sobre la misma empleando la partcula usa un. As, por ejemplo, la frase Un objeto
Ventana usa un objeto Empleado devolvera verdadero.
Reutilizacin
Un objeto bien diseado, puede ser reutilizado en otra aplicacin de modo directo o creando
una clase derivada a partir de l. Este es uno de los objetivos perseguidos por la OOP,
aprovechar en lo posible el cdigo ya escrito, ahorrando un considerable tiempo en el desarrollo
de programas.
VB.Net (Cap 6. OOP)
Pg. 105
Declaracin
En VB.Net la declaracin de un array la haremos usando un par de parntesis en el nombre
de la variable o del tipo, en el siguiente ejemplo declaramos un array de tipo String llamado
nombres:
Estas dos formas son equivalentes.
Dim nombres() As String
Dim nombres As String()
Nota: En los apartados posteriores vers que un array tambin se puede definir de la clase
Array y crear una instancia como se ve en la siguiente instruccin:
Private nombres As Array= Array.CreateInstance(GetType(String), 11) ' Lo declara y
luego lo instancia con CreateInstance. No se puede poner New Array porque la
clase Array no lo permite
Pg. 107
Length,
que nos
Por tanto, si queremos usar esta propiedad para acceder a todos los elementos, debemos tener
en cuenta que el ndice inferior es el 0, por lo que si usamos un bucle para recorrerlo, debemos
hacerlo desde la posicin 0 a 1 menos de la longitud, en la forma:
For i As Integer = 0 To numeros.Length - 1 ' As recorre todos los elementos
lstNum.Items.Add(numeros(i))
Next
Con el cdigo anterior estamos creando un array de tipo String con 4 valores cuyos ndices
van de 0 a 3.
Pg. 108
Para ver las diferencias, crea un formulario con un botn y una lista (lstNum) y copia el
siguiente cdigo:
Dim num0(9) As Integer ' Array de 10 elementos, con valor 0 en cada uno
Dim numNothing() As Integer ' El array no tiene dimensin, vale Nothing
Dim numVacio() As Integer = {} ' El array existe aunque vaco. Tiene longitud 0
MessageBox.Show("num0")
lstNum.Items.Clear()
For i As Integer = 0 To num0.Length - 1 ' Escribe 9 ceros
lstNum.Items.Add(num0(i))
Next
MessageBox.Show("numVacio")
lstNum.Items.Clear()
For i As Integer = 0 To numVacio.Length - 1 ' No escribe nada, porque
numVacio.Length vale 0
lstNum.Items.Add(numVacio(i))
Next
MessageBox.Show("numNothing")
lstNum.Items.Clear()
For i As Integer = 0 To numNothing.Length - 1 ' Se rompe, porque numNothing no
existe, es Nothing y no se puede aplicar ningn mtodo o propiedad
lstNum.Items.Add(numNothing(i))
Next
Pg. 109
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.
Nota: En el apartado de la clase Array vers que tambin podemos redefinir el tamao del
array mediante el mtodo Resize.
Eliminar su contenido
Una vez que hemos declarado un array y le hemos asignado valores, es posible que nos
interese eliminarlos de nuevo.Para lograrlo, podemos hacerlo de dos formas:
Como con cualquier objeto, podemos asignar un valor Nothing al array.
Usar la instruccin Erase que elimina totalmente el array de la memoria.
Si seguimos con el ejemplo del prrafo anterior, las dos instrucciones siguientes son
equivalentes.
numVacio = Nothing ' Antes tena longitud 0, pero exista. Ahora se queda a
Nothing, no existe.
Erase num0 ' Antes tena 10 elementos, ahora se queda a Nothing
Pg. 110
Resize de la
Qu ha ocurrido? Pues que como los arrays son tipos por referencia, solamente existe una
copia de los datos por lo que ambas variables, Ciclos y Otros, contienen una referencia (o
puntero) a los mismos datos.
Si realmente queremos tener copias independientes, debemos hacer una copia del array
Ciclos 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.
Tambin podemos utilizar el mtodo
pero de todo el array.
Clone
Ciclos2 = Ciclos.Clone
En el siguiente cdigo de ejemplo hacemos una copia del contenido del array Cursos en el
array Otros, de esta forma, el cambio realizado en el elemento 0 de Cursos no afecta al del array
Otros.
Dim Ciclos() As String = {"DAM", "ASIR", "AF", "GCM"}
Dim Otros(3) As String ' Tiene que tener un tamao como mnimo de 4 elementos (que
son los que vamos a intentar copiar en este ejemplo)
Ciclos.CopyTo(Otros, 0)
Ciclos(0) = "Dam o Daw"
MessageBox.Show("Ciclos(0) = " & Ciclos(0) & ControlChars.CrLf & "Otros(0) = " &
Otros(0)) ' Ciclos (0) es "Dam o Daw" pero Otros(0) sigue valiendo "DAM"
Cuidado! Si el array que va a recibir la copia no est dimensionado o es menor que lo que
se intenta copiar, se produce un error de ejecucin, como puedes apreciar en la siguiente figura:
Pg. 111
Crear directamente el array al llamar al mtodo. Esta ser especialmente til en los
casos en que solo lo necesitemos para esa llamada.
Dim valores() As Integer = {10, 20, 30}
Dim miSuma As Integer = Suma(New Integer() {10, 20, 30})' Crea el array
directamente en la llamada
Length usada
array
MessageBox.Show("Longitud = " & Ciclos.Length) ' Indicar que tiene 4
Pg. 112
First
Atencin! Recuerda que si el array est a Nothing (por definicin vaca o tras eliminarlo)
no podemos aplicarle ningn miembro al array (propiedad o mtodo), como si de otro objeto se
tratase:
Dim Ciclos() As String
Sub Ejemplo
If Ciclos.Contains("DAM") Then ' Si el array no existe
MessageBox.Show("Ya existe")
End If
End Sub
SE ROMPE!!!
Deberamos controlar primero que realmente existe. Una posible forma es:
Sub Ejemplo
If Ciclos IsNot Nothing AndAlso Ciclos.Contains("DAM") Then ' Si el array
existe y no contiene ese elemento
MessageBox.Show("Ya existe")
End If
End Sub
Clase Array
Para finalizar este tema, solo nos queda por decir, que los arrays de VB.Net realmente son
tipos de datos derivados de la clase Array y por tanto disponen de todos los miembros
definidos en esa clase, como ya hemos ido comentando en el punto anterior.
Atencin Como podrs observar cuando estamos accediendo a un array nos aparecen
mtodos que luego nos dan error de escritura, por ejemplo, si empiezas a escribir
Ciclos.Clear( comprobars que te pide un array y si escribes Ciclos.Clear(Ciclos,2,3) el
IDE te mostrar el error con esta posible solucin (ya que en realidad Clear es un mtodo
compartido de la clase)
Pg. 113
Notas
En el caso de que solo haya una sola aparicin IndexOf y LastIndexOf daran el
mismo valor (ya que sera el nico a encontrar), por lo que esto nos sirve para saber si
es nico.
LastIndexOf da la posicin por la derecha pero contando desde la izquierda, es decir,
en el ejemplo anterior si la palabra fuese ADIOS indica 5.
Clear inicializa los elementos del array que le indiquemos por parmetro,
es decir,
les devuelve los valores por defecto: 0 si es numrico, False en el caso de ser boolean,
para los String,
Array.Clear(Ciclos, 1, 2) ' Deja en blanco las posiciones 1 y 2
Array.Clear(Ciclos, 0, Ciclos.Length) ' Limpia el array completo, desde
la posicin 0 tantos elementos como tiene
Pg. 114
54
1
34
2
121
3
343
4
2
5
0
1
0
2
0
3
0
4
0
5
0
6
0
7
0
2
0
3
34
4
121
5
343
6
0
7
Y otros el siguiente
0
0
0
1
Observa: Una gran ventaja de este mtodo es que podemos dejarlo sin
elementos sin necesidad de eliminar el array.
Si queremos limpiar un array, es decir, poner sus elementos a 0, o False
dependiendo del tipo del array, usaremos el mtodo Clear en la forma:
Array.Clear(numeros, 2, 4) ) ' Pone a los 0 nmeros que hay desde la
posicin 2
Atencin Observa que no hemos puesto cursos = New Array ya que la clase
Array no lo permite por estar declarada como MustInherit, es decir, que no permite
crear un objeto directamente a partir de ella.
Buscar elementos en un array: Para eso tenemos los mtodos Find y
Estos son ms difciles de implementar. Veamos esto con un ejemplo:
FindAll.
Pg. 115
Atencin! Si definimos un array con la clase Array hay mtodos que no existe, como por
ejemplo Contains
Dim palabras() As String = {"hola", "adios", "vale", "si"}
Dim palabrasArr As Array = {"hola", "adios", "vale", "si"}
If palabras.Contains("adios") Then' Estara bien
If palabrasArr.Contains("adios") Then ' No tiene este mtodo
Igualmente la clase String incluye el mtodo Split que nos permite crear un array a partir de
una cadena. Este mtodo trocea una cadena en elementos de un array usando un separador.
Dim frase As String = "Hola*alumn@*de*1DAM"
Dim pal() As String = frase.Split("*") ' Crea un array de 4 elementos: Hola,
alumn@, de y 1DAM
Dim frase As String = "Hola 1DAM"
Dim palabras() As String = frase.Split(" ") ' Devuelve un array con 2 elementos:
Hola y 1DAM, usando el espacio en blanco como separador
Pg. 116
Arrays de objetos
Lgicamente tambin podemos definir arrays con objetos de clase. Para las siguientes
explicaciones vamos a utilizar la clase Localidad definida anteriormente:
Cmo conseguimos que Localidad tenga una propiedad LineasAutobuses que sea un array
de objetos de esta clase?
Podemos definir una variable como los ejemplos anteriores, con cualquiera de estas formas:
Private _LineaAutobuses() As Autobus = {} ' Si queremos que el Array no sea
Nothing
Private _LineaAutobuses As Autobus() = {} ' Recuerda que tambin podamos poner
el () en el tipo
Private _LineaAutobuses As Array = Array.CreateInstance(GetType(Autobus), 0) '
Inicialmente no tenemos ninguno, pero si existe el array
Pg. 117
Pero, cmo definimos la propiedad? Pues en este caso tendremos que indicarle que es array
en el tipo, en la forma:
Public Property LineasAutobuses As Autobus() ' Observa que aqu el () va en el
tipo obligatoriamente
Get
Return _LineaAutobuses
End Get
Set(ByVal value As Autobus()) ' Aqu lo pone as por defecto,pero podemos
cambiarle a Byval value() As Autobus
_LineaAutobuses = value
End Set
End Property
Y si lo que queremos es buscar una localidad en el array de localidades? Podemos usar los
mtodos Contains, IndexOf, comentados anteriormente? S, pero con cuidado.
Nota: Debes tener en cuenta que estos mtodos (a nivel interno) necesitan hacer un
recorrido del array y buscar entre sus elementos si existe alguno igual al recibido por el
parmetro. Pero, Cundo se consideran iguales dos objetos? En principio, y a no ser que se le
indique lo contrario, dos variables se consideran iguales iguales solo cuando apuntan al mismo
objeto (as lo indica el mtodo v). Si queremos hacer otra consideracin deberemos modificar
este mtodo.
Supongamos que hemos definido el array:
Private localidades() As Localidad = {}
Y la siguiente funcin:
Public Sub Aadir(ByVal loc As Localidad)
If localidades.Contains(loc) Then Exit Sub ' No la aade si ya lo tiene,
entiende que est contenida si hay alguna igual (por Equals) a loc
Array.Resize(localidades, localidades.Count + 1)
localidades(localidades.Count - 1) = loc
End Sub
simularlos
con
Pg. 118
Hay otras ocasiones en que puede haber ms de un elemento que cumpla la condicin. En
este caso deberamos devolver todos los elementos o ninguno caso de que no haya.
En este tercer ejemplo vamos a obtener las ciudades que tienen ese nombre. Si no hay
ninguna devuelve un array de longitud 0 (podramos devolver Nothing).
Public Function CiudadesDeNombre(ByVal nombre As String) As Localidad()
Dim c() As Localidad = {}
Dim tc As Integer
If ciudades Is Nothing Then Return c ' o Return Nothing si as se desea
For i As Integer = 0 To ciudades.Length - 1
If ciudades(i).Nombre.ToUpper = nombre.ToUpper Then
tc += 1
Array.Resize(c, tc)
c(tc - 1) = ciudades(i)
End If
Next
Return c
End Function
Pg. 119
Colecciones
Una coleccin es un objeto que sirve para agrupar objetos relacionados, pudiendo aadir o
quitar elementos en tiempo de ejecucin gracias a mtodos preparados para estas tareas.
Toda coleccin estar definida de la clase Collection que nos proporciona funcionalidad
integrada que permite Aadir o/y Borrar elementos con mtodos del tipo: Add, Remove, ,
recorrer en iteracin los miembros mediante la instruccin For Each...Next (la veremos en este
captulo) y recuperar los elementos usando su ndice o una clave String.
Tenemos colecciones con las que ya hemos venido trabajando, y que se encuentran en todo
formulario como las colecciones de elementos Items o elementos seleccionados SelectedItems
incorporadas en toda ListBox o ComboBox , la de controles Controls de todo formulario o
control
contenedor,
la
de
formularios
abiertos
en
la
aplicacin
My.Application.OpenForms
Tipos de coleccin.
Los tipos de colecciones existentes van en funcin de lo que se hace normalmente con el
manejo de sus datos, pudiendo encontrarnos con:
Lista.
Pila.
Cola.
Emparejamiento de datos, clave y valor.
El acceso a dichas colecciones, y sus mtodos, depender del tipo de estructura a la cual esta
dirigida la coleccin.
Este bucle permite recorrer los elementos de una coleccin o array mediante una variable
auxiliar elemento que deber ser del mismo tipo que la coleccin. En cada iteraccin, esta
variable har referencia a un elemento, lgicamente de forma correlativa, es decir, al comienzo
(y siempre que la coleccin no est a Nothing o con Count a 0) elemento har referencia al
primero de la coleccin, en la siguiente vuelta al 2, y as sucesivamente mientras haya
elementos.
For Each elemento As tipoDeLaColeccion In coleccion
instrucciones()
Next
Pg. 120
De la misma forma, si queremos recorrer los diferentes elementos de una ListBox, podemos
hacerlo mediante los dos for siguientes, en los que recorre los diferentes elementos de la
ListBox, y selecciona aquellos que empiecen por B, almacenndolos en una etiqueta.
For i As Integer = 0 To lstCiudades.Items.Count - 1
If lstCiudades.Items(i).StartsWith("B") Then
lblCiudades.Text &= lstCiudades.Items(i) & " "
End If
Next
Es decir, un bucle For Each es equivalente a recorrer con una variable entera desde la
posicin 0 hasta la Count -1.
Supongamos que tenemos una coleccin (o array) de Personas (de la clase Persona). El
siguiente bucle recorrera todas
Private Personas As List(Of Persona) = {}
For Each per As Persona In Personas ' Recorre todas las personas y muestra la
edad de aquellas que se llamen igual al valor que est en la caja de texto.
If per.Nombre = txtNombre.Text Then
MessageBox.Show (per.Edad)
End If
Next
Lgicamente si deseamos recorrer la coleccin en otro orden, orden inverso, recorriendo solo
los elementos pares, deberemos usar siempre el For tradicional.
Cuidado! No podremos utilizar este bucle si lo que deseamos es borrar alguno de sus
elementos. Observa el siguiente ejemplo:
Pg. 121
Aparentemente ira recorriendo los diferentes elementos y los ira eliminando, de la misma
forma que tampoco podramos usar su equivalente, ya que tras borrar el primer elemento,
detecta que la coleccin ha cambiado y se la.
For i As Integer = 0 To Ciudades.Count 1 ' Como en el caso anterior, error
Ciudades.Remove(Ciudades(i))
Next
coleccin
Pg. 122
Pg. 123
Coleccin de controles
Cada formulario o control contenedor (ejemplo: GroupBox), est formado por una propiedad
Controls que contiene la coleccin de controles de los que est compuesto el formulario (o
control). Esto nos permitir recorrerlos como en los casos anteriores.
Veamos un ejemplo, en el que intentamos limpiar todas las cajas de texto que haya en el
formulario. Para eso podemos recorrer todos los controles, analizando para cada uno de ellos, si
es o no una caja de texto, y solo en el caso de que lo sea se limpiar su texto. Esto lo podremos
hacer con cualquiera de los dos For (si no entiendes el For Each vete al apartado anterior donde
se explica).
For Each miControl As Control In Me.Controls ' Recorre todos los controles
If miControl.GetType = GetType(TextBox) Then ' Si el control es una caja de
texto
TryCast(miControl, TextBox).Clear() ' Limpia la caja de texto
End If
Next
Expliquemos un poco el cdigo. El For Each nos permite recorrer todos los controles de la
coleccin Controls del formulario.
Cuidado! Aunque solo queramos pasar por las cajas de texto, la variable deberemos
declararla del tipo de la coleccin. El siguiente bucle dara error de ejecucin
For Each txt As TextBox In Me.Controls ' Como va recorriendo todos los controles,
al encontrarse con un control que no sea caja de texto, se producira una
excepcin
Una vez que nos encontramos en un control, debemos saber si es una caja de texto, y para
eso preguntaremos si su tipo coincide con el de la clase TextBox (es decir, si es una caja de
texto). Esta pregunta se puede hacer de ms formas, por ejemplo:
If miControl.GetType.Name = -"TextBox" Then ' Si el nombre del tipo es TextBox
Observa el formulario de
la imagen. La coleccin
Me.Controls del formulario
solo tiene 3 controles: el
marco de Ventas, el de Nuevo
artculo y el botn Fin
programa. Los otros controles
no pertenecen a esa coleccin
sino al marco correspondiente:
Me.grbVentas.Controls
Pg. 124
En este ejemplo indicamos que el control que aadimos pertenece a la coleccin de controles
del formulario (por poner la palabra Me o si no la ponemos).
Si queremos que esta coleccin est dentro de otro control lo indicaramos poniendo
Controls como mtodo del control propietario.
Ejemplo:
grbTenderos.Controls.Add(boton)
Ya tenemos el o los controles creados, ahora nos falta conectar los eventos del botn (en el
siguiente ejemplo lo haremos con el evento Click) con un procedimiento ya declarado (ver
ejemplo con BotonClic). Para poder asociarlo usaremos la palabra clave AddHandler,
pasndole la direccin del procedimiento a asociar con AddressOf. Si necesitamos quitar esta
asociacin tenemos RemoveHandler.
AddHandler boton.Click, AddressOf BotonClic
Pg. 125
Recuerda que la variable sender (le puedes poner otro nombre, aunque no es habitual)
indica el objeto sobre el que se ha realizado el evento (en este caso el clic). El subprograma de
arriba mostrara un mensaje con el texto del control. Pero como sender es una variable Object
genrica es mejor hacer una conversin de tipo en cualquiera de las formas planteadas a
continuacin:
Private Sub BotonClic(ByVal sender As Object, ByVal e As System.EventArgs)
frmTienda.Text = TryCast(sender, Button).Text) ' Convertir el objeto Object al
tipo correspondiente
End Sub
Aunque en este caso las tres formas de conversin seran vlidas, tienen ciertas diferencias.
sirven para todos los tipos de datos, TryCast solo para tipos por referencia
(veremos estos conceptos ms adelante).
Ctype y DirectCast
Otra cosa que les diferencia, es como tratar los posibles errores de conversin. Supongamos
que el procedimiento BotonClic tambin est asociado a un evento de otro tipo de control, por
ejemplo, de una etiqueta. Al intentar hacer la conversin, Ctype y DirectCast produciran un
error de ejecucin InvalidCastException, mientras que TryCast devuelve el valor Nothing,
de modo que en lugar de controlar la posible excepcin, slo debemos comprobar el resultado
devuelto con Nothing.
Por tanto, para controlar los posibles errores tenemos varias posibilidades:
Averiguar el tipo antes de intentar hacer la conversin, en cualquiera de las formas
siguientes:
Mediante el mtodo GetType:
If
el
If
el
Incluso con la funcin de VB TypeName (aunque este caso mejor dejarlo ya como obsoleto):
If TypeName(sender) = "Button" Then
O bien directamente:
If TryCast(sender, Button) Is Nothing Then Exit Sub
Pg. 126
Igualmente si conocemos el control por otro motivo, como por ejemplo, si es el objeto sobre
el que se ha producido un evento:
Private Sub BotonClic(ByVal sender As Object, ByVal e As System.EventArgs)
Me.Controls.Remove(sender) ' elimina el control sobre el que se ha producido
el evento
End Sub
Pg. 127
Si al hacer clic sobre el botn pones uno de estos dos bucles vers que deja una etiqueta sin
borrar con el primer For (el For Each) y en el segundo adems de no borrar la segunda etiqueta
da error de ndice ya que la i intenta llegar a un valor 3 que ya no existe.
El motivo de que no borre la etiqueta Labe2 es porque en la iteraccin, al borrar la Label3
(primera que borrara) la Label2 cambia de posicin en la coleccin de los Controls (antes
estaba en la posicin 1 y ahora en la 0) por lo que se da ya por analizada y por tanto no la
borrar.
For i As Integer = Me.Controls.Count 1 To 0 Step -1
descendente
If Me.Controls(i).GetType = GetType(TextBox) Then
Me.Controls.Remove(Me.Controls(i))
End If
Next
El mtodo Find tiene un segundo parmetro para indicar si se deben buscar los controles
secundarios o no. Se consideran controles secundarios los que estn dentro de un control que
est dentro de este. Si observas el formulario del apartado Coleccin de controles si
Dim controles() As Control = Me.Controls.Find("btn", False) ' Busca todos los
controles que hay directamente en el formulario con ese nombre. Si no hay ninguno
controles tendr longitud 0. Si hay alguno pero esta dentro de un marco no lo
reconoce.
Dim botones() As Control = Me.Controls.Find("btn", True) ' Como en el caso
anterior, pero en este caso busca en el formulario y en los contenedores que
estn dentro de l, es decir, si hay en algn marco, panel, .. tambin los
devuelve.
Pg. 128
Pg. 129
Pg. 130
Cmo podemos definir nuestras propias colecciones? Veamos una forma con la coleccin
ArrayList.
La clase ArrayList
Los objetos de tipo coleccin creados con la clase ArrayList, implementan un array cuyo
nmero de elementos puede modificarse dinmicamente, permitiendo aadir, eliminar y
modificar fcilmente los elementos que contiene. Tambin podemos recorrerlos mediante un
bucle For accediendo a los elementos por medio de un ndice o con un For Each pasando por
cada uno los elementos en la iteraccin (ver punto anterior).
Al igual que ocurre con los arrays, el ndice inferior es siempre cero y los elementos se
almacenan de forma consecutiva, es decir, si aadimos dos elementos a una coleccin de tipo
ArrayList, el primero ocupar la posicin cero y el segundo la posicin uno. La ventaja de
trabajar con las colecciones es que no debemos preocuparnos de reservar memoria cada vez que
vayamos a aadir un nuevo elemento, simplemente usamos el mtodo Add y asunto arreglado.
Lo mismo ocurre a la hora de quitar elementos de una coleccin, no tenemos que
preocuparnos demasiado por el espacio dejado al quitar elementos, de eso se encarga el propio
.NET, nosotros simplemente debemos llamar al mtodo Remove o RemoveAt indicando
respectivamente el elemento a eliminar o el ndice en el que se encuentra almacenado.
Cuidado! Si decidimos eliminar varios elementos de una coleccin de tipo ArrayList (al
igual que ocurra con los arrays normales), lo normal es que lo hagamos usando un bucle For;
pero recuerda que debemos recorrer el bucle desde el final hacia adelante, con idea de que al
cambiar el nmero de elementos no falle intentado acceder a un elemento que ya no existe.
Observa que si intentamos acceder a las diferentes listas, en el caso de ciudades1 puede que
no exista (en las otras s aunque tenga tamao 0).
Ejemplo. Si intento acceder a ciudades1 despus de la declaracin anterior, se producir un
error de ejecucin:
For Each c As Ciudad In ciudades1
' trabajar con c
Next
Pg. 131
Pg. 132
Pg. 133
El resultado sera:
Pg. 134
Pg. 135
Y RecorrerArray
Sub RecorrerArray(ByVal etiqueta As Label, ByVal Valores As Array)
For Each elem As String In Valores
etiqueta.Text &= elem & ","
Next
'For i As Integer = 0 To Valores.Length - 1 ' En arrays la propiedad es Length
'
etiqueta.Text &= Valores(i) & ","
'Next
End Sub
El objeto pasado deber ser del tipo, por lo que si estamos con el String, lo siguiente tiene
sentido:
If Datos.Contains("Tontera") Then MessageBox.Show("Si contiene el string
Tontera")
MessageBox.Show(Datos.IndexOf("Tontera")) ' Devuelve la posicin 3
MessageBox.Show(Datos.IndexOf("Otra cosa")) ' Devuelve la posicin -1 pues no
contiene este String
Pg. 136
Pero cuidado! Porque el siguiente cdigo puede parecer extrao aunque en el fondo es muy
lgico:
Dim pers As New Persona("Mara", 25) ' Nueva persona con estos datos
MessageBox.Show(Datos.Contains(pers)) ' Devuelve False ya que pers es una nueva
persona, y aunque coincida en los datos con el elemento 0 de Datos NO es el mismo
objeto a no ser que en la clase persona hayamos modificado el/los mtodos Equals.
Ejemplo indicando que dos personas son iguales cuando les coincide el Nombre (o
el nombre y la edad, o)
Public Overloads Function Equals(ByVal per As Persona) As Boolean
Return Me.Nombre = per.Nombre
End Function
O bien:
Dim per As New Persona(txtNombre.Text, txtEdad.Text)
pPersonas.Add(per)
Tambin podemos borrar un elemento conociendo el ndice, (que generalmente ser como lo
hagamos) en la forma:
VB.Net (Cap 7. Arrays y Colecciones)
Pg. 137
Y por ltimo, para recorrer las distintas personas podramos usar el For Each tpico:
For Each p As Persona In pPersonas
Me.ListBox1.Items.Add(p.Nombre)
Me.ListBox2.Items.Add(p.Edad)
Next
ArrayList de objetos
Cuidado, si lo que tenemos es un ArrayList de objetos de una clase, como en este enunciado,
las cosas se pueden complicar un poco.
Veamos unos ejemplos:
Private Sub btnAceptar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnAceptar.Click
Dim pers As New ArrayList
Dim p As New Persona
p.Nombre = "Mara"
p.Edad = 30
pers.Add(p)
MostrarValores(Label1, pers)
p = New Persona("Pili", 34)
pers.Add(p)
MostrarValores(Label2, pers)
p = New Persona("Antonio", 20)
pers.Add(p)
MostrarValores(Label3, pers)
p = New Persona("Ignacio", 40)
pers.Add(p)
p = New Persona("Demi", 18)
pers.Add(p)
MostrarValores(Label4, pers)
Dim pc As New ArrayList
p = New Persona
p.Nombre = "Maramod"
p.Edad = 45
pc.Add(p)
p = New Persona
p.Nombre = "Pilimod"
p.Edad = 10
pc.Add(p)
pers.SetRange(0, pc)
MostrarValores(Label5, pers)
End Sub
Pg. 138
Colecciones generic
Como hemos visto, un ArrayList almacena los elementos como una referencia a un objeto de
tipo Object, por lo que cada vez que utilicemos una coleccin debemos tomar precauciones si
nuestra intencin es que solo se puedan almacenar elementos de un tipo determinado.
Como representacin de colecciones
List (Of T)
En este caso definimos una coleccin basndonos en una clase en concreto, y ser el propio
compilador quien detecta el error en el caso de que intentemos aadirle un objeto que no sea de
la clase declarada, como puedes apreciar en el siguiente trocito de cdigo:
Ejemplo. Sunpongamos que tenemos una clase Biblio con la siguiente definicin:
Private _Personas As New List(Of Persona)
_Personas.Add(per) ' Instruccin permitida en un Sub o Function, siempre que per
sea de la clase Persona
_Personas.Add(btnFin) ' Si btnFin es un Button, dara como ERROR DE COMPILACIN:
Un valor de tipo System.Windows.Forms.Button no se puede convertir en Persona
La forma de usar una lista de este tipo, ser semejante a todo lo explicado para ArrayList.
Ejemplo, si tenemos una clase Libro con un constructor que permite crearlo pasndole el ttulo,
autor, precio y editorial, la siguiente declaracin creara una lista con 2 libros.
Private libros As New List(Of Libro) From {
New Libro("El camino", "Miguel Delibes", 18, "Ediciones Destino"),
New Libro("Terapia Gestalt", "Carmen Vazquez", 11.5, "Ctp")
}
A veces tenemos algunos cambios con respecto a los ArrayList, como por ejemplo,
determinar que una coleccin sea de solo lectura. Veamos como lo haramos en los dos casos.
Supongamos que continuamos con la coleccin anterior _Personas de la clase Grupo:
Podemos definir una propiedad que nos muestre y permita modificar estas personas:
Public Property Personas As List(Of CPersona) ' Podr hacer los cambios que desee
Get
Return _Personas
End Get
Set(ByVal value As List(Of CPersona))
_Personas = value
End Set
End Property
Es decir, las siguientes instrucciones son todas vlidas (con el objeto miGrupo de la clase
Grupo):
miGrupo.Personas.Add(New Persona()) ' Aade una nueva persona a la coleccin
miGrupo.Personas = otraLista ' Personas cambia totalmente con la otra lista
miGrupo.Personas(0).Nombre = "Mara" ' Cambia el nombre de la primera persona
Pero hay ocasiones en que no queremos permitir que modifiquen una lista. Para conseguir
esto, posiblemente se nos ocurrira definir una propiedad de solo lectura en la forma:
Public ReadOnly Property PersonasRO As List(Of CPersona) ' Devuelve la coleccin
tal cual, al ser ReadOnly la Property, no podremos hacer una asignacin
PersonasRO = OtrasPersonas pero S podr hacer PersonasRO.Add(persona)
Get
Return _Personas
End Get
End Property
Pg. 139
Con esto solo conseguimos que no se pueda hacer una asignacin completa (del estilo
miGrupo.Personas = otraLista), pero s seran validas las otras posibilidades.
miGrupo.PersonasRO.Add(New Persona()) ' Esto est permitido, e igual que en el
ejemplo anterior, aade una nueva persona a la coleccin
miGrupo.PersonasRO = otraLista ' ERROR DE EJECUCIN, ya que no existe el Set de
la propiedad
miGrupo.PersonasRO(0).Nombre = "Mara" ' Permitido, y como antes, pone nombre a
la primera persona (o lo cambia si ya tena uno)
Para acercarnos a lo que deseamos, deberamos usar el mtodo AsReadOnly de las List(Of
T), teniendo en cuenta que no nos devuelve una List(Of T) sino una coleccin de solo lectura:
System.Collections.ObjectModel.ReadOnlyCollection(Of T). La propiedad quedara:
Public ReadOnly Property PersonasSoloLect As
System.Collections.ObjectModel.ReadOnlyCollection(Of CPersona)
Get
Return _Personas.AsReadOnly
End Get
End Property
Ahora solo admitira el cambio de algn campo, ya que eso no podremos evitarlo de ninguna
forma:
miGrupo.PersonasSoloLect = New List(Of CPersona) ' ERROR DE COMPILACIN, Es una
propiedad de solo lectura
Si buscamos el mtodo Add, veremos que ni siquiera lo tiene, es decir, no se puede escribir
miGrupo.PersonasSoloLect.Add
miGrupo.PersonasSoloLect(0).Nombre = "Mara" ' Permitido, y como en todos los
casos, cambia el nombre a la primera persona
Ahora solo admitira el cambio de algn campo, aunque tengamos los mtodos:
miGrupo.PersonasAListRO.Add(New Persona()) ' ERROR DE EJECUCIN, no permite usar
los mtodos que cambien la coleccin entera
miGrupo.PersonasAList = otraLista ' ERROR DE EJECUCIN, al igual que en el caso
anterior, pues no tiene el Set de la proiedad
TryCast(miGrupo.PersonasAlistRO(0), CPersona).Nombre = "Mara" ' Permitido, y
como en todos los casos, cambia el nombre a la primera persona
Pg. 140
Cap 8. Herencia
Se trata de la caracterstica ms importante de la OOP, y establece que partiendo de una clase
a la que denominamos clase base, padre o superclase, creamos una nueva clase denominada
clase derivada, hija, o subclase. En esta clase derivada dispondremos de todo el cdigo de la
clase base, ms el nuevo cdigo propio de la clase hija, que escribamos para extender sus
funcionalidades.
A su vez podemos tomar una clase derivada, creando una nueva subclase a partir de ella, y
as sucesivamente, componiendo lo que se denomina una jerarqua de clases, que explicaremos
seguidamente.
Existen dos tipos de herencia: simple y mltiple. La herencia simple es aquella en la que
creamos una clase derivada a partir de una sola clase base, mientras que la herencia mltiple nos
permite crear una clase derivada a partir de varias clases base. El entorno de .NET Framework
slo permite utilizar herencia simple.
Un ejemplo sera disponer de nuestra ya conocida clase Persona. Si intentamos definir una
nueva clase Empleado indicando que hereda de la clase Persona, ya que todo empleado es, por
supuesto, una persona. En esta nueva clase tendramos que aadir las nuevas propiedades y
mtodos que le confieren en empleado: Ejemplo FechaEntrada, Sueldo, mientras que el
Nombre, FechaNacimiento, ya lo tendra por el mero hecho de de haber heredado de
Persona.
Jerarquas de clases
Uno de los fines de la OOP consiste en la clasificacin del cdigo; para ello se emplean
jerarquas o rboles de clases, en los que a base de niveles, se muestra un conjunto de clases
conectadas por una relacin de herencia como podra verse en la siguiente figura:
En esta representacin de ejemplo, como nivel superior de la jerarqua o clase base estara
Medios de transporte, de la que se derivaran las clases Barco, Tren, Automvil, y a su
Pg. 141
Una vez que creemos la clase derivada, tendremos a nuestra disposicin todos los elementos
de la clase base, tanto desde la propia clase, como desde el cdigo cliente.
Public Class Profe : Inherits Persona
Private _Sueldo As Decimal
Public Property Sueldo() As Decimal
Get
Return _Sueldo
End Get
Set(ByVal value As Decimal)
If value < 500 Then
Throw New Exception("No puede ser inferior a 500")
End If
_Sueldo = Sueldo
End Set
End Property
End Class
Pg. 142
Protected
Un miembro de clase declarado con este modificador, ser accesible desde el cdigo de su
propia clase y desde cualquier clase heredada, pero no desde una instancia del objeto. El
siguiente cdigo muestra un ejemplo del uso de Protected. Supongamos que en la clase Persona
definimos la siguiente propiedad:
Protected ReadOnly Property Apellidos() ' En Persona
Get
Return Nombre.Apellido1 & " " & Nombre.Apellido2
End Get
End Property
Sin embargo si intentamos instanciar una variable de la clase Profe (o Persona, da igual), no
podramos acceder a dicha propiedad.
Dim pr As Profe, per As Persona
MessageBox.Show(pr.Apellidos) ' Imposible, no tiene esta propiedad
Friend
Un miembro de clase declarado con este modificador, ser accesible por todo el cdigo de su
proyecto o ensamblado. Es decir, si tenemos la clase y su uso en el mismo proyecto, equivaldra
a Public, pero si la clase est en una DLL, se considerara como privada, puesto que no
podramos acceder a ella.
Aunque hemos descrito su modo de manejo a travs de clases, la palabra clave Friend
tambin puede ser utilizada como modificador de mbito para variables y procedimientos
situados en mdulos de cdigo. (En este caso recuerda que importbamos la clase con
Imports).
Pg. 143
Protected Friend
Los miembros de clase declarados al mismo tiempo con Protected y Friend, obtendrn una
combinacin de ambos modificadores; por lo tanto, sern accesibles desde el cdigo de su clase,
clases derivadas, y por todo el cdigo que se encuentre dentro de su ensamblado
Podramos definir una nueva Edad en Profe como se muestra en el siguiente cdigo.
Observa que para que reconozca la variable _fechaNacimiento declarada en Persona, deber
tener un mbito de Protected, para que desde el programa no se pueda acceder a ella pero si
desde su clase derivada.
Public Overloads Function Edad(ByVal fecha As Date) As Integer
If _fechaNacimiento = #12:00:00 AM# Then ' _fechaNacimiento est declarada
Protected en Persona
Throw New Exception("No conoce la fecha de nacimiento")
End If
Edad = fecha.Year - _fechaNacimiento.Year
If fecha.Month < _fechaNacimiento.Month Or (fecha.Month =
_fechaNacimiento.Month And fecha.Day < _fechaNacimiento.Day) Then
Edad -= 1
End If
End Function
Pg. 144
Supongamos por ejemplo, que para que una persona pueda trabajar, obligatoriamente debe
tener una edad superior a 16 aos. Si modificamos la propiedad FechaNacimiento en la clase
Persona en la forma.
Public Overridable Property FechaNacimiento() As Date
' Overridable para que se pueda reescribir
Get
Return _fechaNacimiento
End Get
Set(ByVal value As Date)
If DateDiff(DateInterval.Day, value, Today) < 0 Then
Throw New Exception("La fecha de nacimiento no puede ser superior a
la actual")
End If
_fechaNacimiento = value
End Set
End Property
Pero adems usamos otra clase Cargo que deriva de la anterior, y que su salario se calcula
en base al anterior pero aadiendo un plus dependiendo del tipo de cargo. El nuevo mtodo
quedara:
Public Class Cargo : Inherits Profe
Public Overrides Function Salario() As Decimal
' Se basa en el de su clase base
_Salario = MyBase.Salario
_Salario += _Plus(_tipoCargo)
Return _Salario
End Function
Pg. 145
Debido a cuestiones de diseo, en algunas ocasiones precisaremos que al mismo tiempo que
sobrescribimos un miembro dentro de una clase heredada, dicho miembro no pueda ser
sobrescrito por las clases que hereden de esta. En estas situaciones, al declarar el miembro,
usaremos la palabra clave NotOverridable.
Si mantenemos el ejemplo anterior, supongamos que an podemos tener otras clases que
siguen heredando de la anterior, pero no queremos que estas puedan modificar ya la forma de
calcular el salario, en ese caso la definicin habra sido:
Public Class Cargo : Inherits Profe
Public NotOverridable Overrides Function Salario() As Decimal
End Class
Pg. 146
Un ejemplo sera:
Public Class Profe : Inherits Persona
Public Sub New(ByVal nombre As NombreCompleto, _
ByVal fechaNac As Date, ByVal sueldo As Decimal)
MyBase.New(nombre, fechaNac)
Me.Sueldo = sueldo
End Sub
End Sub
Finalmente, debemos apuntar dos reglas que debe cumplir todo mtodo constructor de una
subclase que llame al constructor de su clase base: en primer lugar, el constructor base debe ser
llamado en la primera lnea del constructor derivado; en segundo lugar, el constructor base slo
puede ser llamado una vez desde el constructor derivado.
Pg. 147
Por lo que si intentamos declarar una variable de la clase Persona el propio compilador nos
indicar el siguiente mensaje de error:
Dentro de una clase abstracta podemos implementar propiedades y mtodos, en la forma que
hemos visto hasta el momento. Adicionalmente, podemos obligar a que determinados miembros
sean sobrescritos por la clase heredada; son los denominados miembros abstractos, y se
declaran usando la palabra clave MustOverride, como vemos en el siguiente cdigo:
Public MustInherit Class Persona
' mtodo abstracto: Este mtodo debe ser sobrescrito por la clase derivada
' En este caso solo escribimos la cabecera, sin cdigo
Public MustOverride Sub MesesActivo()
Public Sub New() ' Resto de miembros...
Debemos tener en cuenta que los miembros abstractos slo tienen sentido si son declarados
en clases abstractas. Por tal motivo, slo podremos crear mtodos con MustOverride en clases
que hayan sido definidas como MustInherit.
Pg. 148
Resumiendo
Toda clase creada hereda de una clase base. Aunque no se haga explcito, todas heredan de la
primera clase: Object, que se encuentra en el espacio de nombres System, es decir,
implcitamente es como si pusisemos: Inherits System.Object
La herencia nos permite la reuntilizacin de cdigo.
Palabras clave de la CLASE BASE (aparecen delante de Class)
Por defecto todas pueden ser heredadas y sus miembros no redefinidos. Para cambiar estos
comportamientos tenemos:
NotInheritable: Clase sellada o no heredable. La clase no puede ser heredada. Ejem: Los
tipos de datos base, no se puede heredar de Integer. Ejemplo la clase Array: no se puede
heredar.
MustInherit: Clase abstracta o no instanciable. Debe ser obligatoriamente heredada para
poder acceder a sus miembros. Aunque tenga mtodo constructor solo ser accesible
desde la clase derivada.
Palabra clave de la CLASE DERIVADA (Debe ser la primera lnea)
Inherits: Hereda de otra clase existente.
Palabra clave de los MIEMBROS de la clase BASE (aparecen delante del nombre del
miembro)
Overridable: Puede ser redefinido. Si se define Public no puede ser redefinido.
NotOverridable: No puede ser sobrescrito por las clases heredadas. Esto ser cuando sea
un miembro que estamos rescribiendo. Ejemplo: Tenemos una clase derivada que
sobrescribe el mtodo Sueldo
Public NotOverridable Overrides Function Sueldo As Decimal
MustOverride: Debe ser obligatoriamente sustituido.
El mbito de las variables o miembros puede ser:
Public: Se puede acceder desde cualquier aplicacin que utilice la clase.
Private: Se puede acceder a ese miembro solo desde el mdulo en que es declarado.
Todas las variables locales deben serlo, y ninguna otra clase (ni las derivadas) o
aplicaciones podrn verlas.
Protected: Los miembros protegidos tienen mbito pblico y privado, ya que se puede
acceder a ellos en la clase derivada, pero no en las aplicaciones que utilicen estas clases.
En la clase derivada tiene un mbito privado.
Friend: Es accesible por todo el cdigo del proyecto o ensamblado.
Protected Friend: Combinacin de los dos anteriores. El miembro est disponible para la
propia clase, para las que heredan de ella y para cualquier otro componente del mismo
ensamblado (pero no si se usa la clase en otros proyectos).
Palabras clave de los MIEMBROS de clase DERIVADA
Overrides: (Sobre-escritura de miembros) Indica que el miembro de la clase derivada
sustituye al de la clase base. No se puede usar para aquellos miembros que fueron
declarados NotOverridable o Protected en la clase base. Es decir, el nuevo miembro altera
parcial o totalmente la implementacin existente del mismo miembro en la clase base. En
este caso, el sobrescrito puede tener absolutamente la misma apariencia que el que
sobrescribe.
Pg. 149
Pg. 150
Pg. 151
El emisor de eventos
Un emisor de eventos, tambin denominado origen de eventos (event source o event sender),
es un objeto capacitado para generar y lanzar eventos al sistema, que puedan ser recuperados
por otros objetos preparados para realizar su tratamiento.
Para que un objeto pueda desencadenar eventos, en su clase debemos realizar dos tareas:
Declarar el propio evento usando la palabra clave Event, especificando si es necesario una
lista de parmetros que acompaan al evento.
Lanzar el evento mediante la palabra clave RaiseEvent, seguida del nombre del evento. Si
lo hemos declarado con parmetros, deberemos aadir los valores para cada uno de los
parmetros en el mismo orden en el que los hemos declarado.
Situndonos pues ante el problema planteado por la clase Empleado en un apartado anterior,
la solucin que proponemos consistir en generar desde la clase Empleado un evento cuando se
produzca un fallo en la validacin del sueldo. De esta manera, el cdigo cliente que lo necesite,
responder al evento; y el que no lo precise, har caso omiso del evento lanzado.
En primer lugar, declaramos en la zona de declaraciones de la clase el evento LimiteSueldo,
que ir acompaado de un parmetro que nos informar del importe errneo que se intentaba
asignar a la propiedad.
A continuacin, en la propiedad Sueldo, cuando detectemos que el sueldo sobrepasa el valor
permitido, en lugar de lanzar el error, generaremos el evento LimiteSueldo, que podr ser
recuperado por el cdigo cliente que haga uso de la clase, actuando como necesite en cada
ocasin. Observa, que al mismo tiempo que lanzamos el evento, le pasamos el importe del
sueldo que se intentaba asignar. Veamos el siguiente cdigo:
Pg. 152
RaiseEvent LimiteSueldo(Value)
End If
mSueldo = Value
End Set
End Property
End Class
Con estas modificaciones sobre la clase Empleado, ya tenemos listo nuestro emisor de
eventos. Queda ahora por completar la parte que captura los eventos lanzados por el emisor.
El receptor de eventos
Un receptor de eventos, tambin denominado manipulador de eventos (event receiver o event
handler), es aquella parte del cdigo cliente, que configuramos para que sea capaz de recibir los
eventos generados por un objeto emisor. Para que ambos elementos, en este canal de
comunicacinque es la transmisin de eventos puedan operar, es necesario conectarlos.
Pg. 153
A continuacin, tenemos que escribir el procedimiento manipulador, que ser invocado cada
vez que se dispare el evento. Dicho procedimiento debe ser de tipo Sub, ya que un evento no
puede devolver valores, por lo que no podremos utilizar un Function; tambin debemos finalizar
su declaracin con la palabra clave Handles, seguida del nombre de la variable del objeto que
hemos declarado en la zona de declaraciones, y el nombre del evento que el procedimiento va a
tratar. En el Cdigo fuente, el procedimiento mEmple_LimiteSueldo( ), ser llamado cada vez
que se produzca el evento LimiteSueldo en el objeto Empleado.
Private Sub mEmple_LimiteSueldo(ByVal importe As Double)
Handles
mEmple.LimiteSueldo
MessageBox.Show("Error en el sueldo " & importe & " que se quiere asignar
a " & mEmple.Nombre)
End Sub
Como siempre, el nombre utilizado para el procedimiento puede ser cualquiera, aunque
generalmente usaremos la convencin NombreObjeto_NombreEvento para facilitar la lectura
del cdigo, aunque ya sabemos que podramos haber empleado otro, como se muestra en el
siguiente cdigo fuente:
Public Sub Sobrepasado(ByVal importe As Double) Handles mEmple.LimiteSueldo
Pg. 154
Pero seguiramos limitados, en el caso de que necesitramos pasar cualquier otro tipo de
informacin que no estuviera directamente relacionada con el objeto.
Para solucionar este problema, podemos utilizar la tcnica empleada por la propia plataforma
.NET en la retransmisin de eventos, y que explicamos a continuacin. La jerarqua de clases de
Pg. 155
.NET dispone de la clase EventArgs, diseada para guardar la informacin adicional que
pasamos a un procedimiento manipulador de evento.
Podemos crear una clase que herede de EventArgs, y adaptarla, en este caso, para que
contenga la informacin adicional sobre un evento que se ha producido en la clase Empleado, de
modo que cuando se ejecute su manipulador asociado, pasemos a dicho manipulador, como
primer parmetro, el propio objeto Empleado, y como segundo, un objeto de nuestra clase
EventArgs personalizada, con datos adicionales sobre el evento generado. Este es el esquema
general de trabajo con los eventos en .NET.
Vamos a definir una nueva clase Empleada (semejante a la anterior pero en la que haremos
ciertos cambios), y una segunda clase EmpleadaEventArgs, que hereda de EventArgs, y que
servir para que cuando a un objeto Empleada se le intente asignar un sueldo incorrecto, se
almacene en ella dicho valor errneo. Veamos este ejemplo:
' Clase EmpleadaEventArgs, para guardar informacin sobre los eventos lanzados
por la clase Empleada. Esta clase en concreto, guardar el valor del sueldo
errneo que se ha intentado asignar a una empleada
Los nombres empleados en la declaracin del evento de esta clase: sender, para designar al
emisor del evento; y e, para designar los argumentos del evento, no son en absoluto
obligatorios, pudiendo utilizar los nombres que deseemos, pero es ms aconsejable seguir la
misma convencin que utiliza la plataforma.
Pg. 156
Supongamos ahora, que queremos que, adems de informar al usuario de lo que est
ocurriendo, queremos que pueda cancelar el valor a asignar. En este caso nos inventaramos una
nueva propiedad en la clase EmpleadaEventArgs.
Private mCancelar As Boolean
Public Property Cancelar() As Boolean
Get
Return mCancelar
End Get
Set(ByVal value As Boolean)
mCancelar = value
End Set
End Property
Este es la forma en que trabajaremos habitualmente para lograr que los eventos de nuestras
clases tengan una estructura semejante al resto de eventos de las clases pertenecientes a la
plataforma.
Pg. 157
Descripcin
Close
ReadLine
Lee una lnea de caracteres del stream actual y devuelve los datos como
String.
ReadToEnd
Read
End Class
Pg. 159
O bien:
Dim fichero As New StreamReader(rutaFichero)
Do Until fichero.EndOfStream
Aqu pregunta por el Fin de Fichero
Dim linea As String = fichero.ReadLine
' la variable linea guarda la lnea del fichero y
'fichero.EndOfStream se pone a True o False dependiendo de si es la ltima o
no
' Aqu pondramos las instrucciones para trabajar con lo ledo en linea
Loop
fichero.Close
Descripcin
Cierra el StreamReader y el stream subyacente.
Escribe en el archivo.
Escribe datos tal y como son especificados por los parmetros sobrecargados,
seguidos de una lnea de terminacin, en definitiva, escribe una nueva lnea.
Limpia el buffer para el actual writer y provoca que cualquier dato contenido en
el buffer sea escrito al stream subyacente.
Pg. 160
Clase File
Otra forma de trabajar con los ficheros, es utilizando la clase compartida File
(que tambin se encuentra en el espacio de nombres de System.IO) con los siguientes mtodos.
Mtodo
Descripcin
OpenText
ReadAllLines Abre el fichero de texto, lee todas las lneas y a continuacin lo cierra.
Devuelve un array de string.
CreateText
Es decir, las dos instrucciones siguientes seran equivalentes, ambas intentan abrir un
fichero que deber existir previamente.
Dim fic As New StreamReader("c:\Test.txt")
Dim fic As StreamReader = File.OpenText("c:\Test.txt")
En los dos casos, por tanto, solo hemos abierto el archivo, ahora seguiramos trabajando con
l, como en lo comentado anteriormente.
Nota: Si usamos File.CreateText y el archivo especificado no existe se crea, y si existe se
sobrescribe (es decir, siempre se crea de nuevo, no tiene opcin de Append).
Ejemplo:
Dim fich As StreamReader = File.OpenText(nomFichero)
Do While Not fich.EndOfStream
Me.lstDatos.Items.Add(fich.ReadLine)
Loop
fich.Close()
Igualmente, si queremos crear un fichero con datos podemos hacerlo tambin con las
siguientes formas:
Con CreateText:
Dim fichero As StreamWriter = File.CreateText(fich)
' Recuerda que eso equivale a: Dim fichero As New StreamWriter(fich)
For Each per As st_Persona In Personas ' Personas sera un array de tipo
st_Persona
fichero.WriteLine(per.Nombre & "*" & per.Apellidos)
Next
fichero.Close()
Pg. 161
O(bien)
File.WriteAllText(nomFichero, txtTexto.Text) ' Abre, graba el texto y lo cierra
Pero, qu ocurre con los posibles errores de ejecucin, ejemplo si el fichero no existe? Si
necesito tratar este caso, tenemos, como siempre varias posiblidades:
Usando la instruccin Try que nos detecte el error:
Dim nomFichero As String = My.Application.Info.DirectoryPath & "\Ejemplo.txt"
Try
Dim sr As New StreamReader(nomFichero)
Do Until sr.EndOfStream
Dim linea As String = sr.ReadLine
' Tratamiento de linea
Loop
sr.Close()
Catch ex As FileNotFoundException
' Instrucciones a ejecutar en el caso de que se produzca en concreto el error
de no existir
Catch ex As IOException
' Instrucciones a ejecutar si se produce otro posible error de fichero
Catch ex As Exception
' Instrucciones a ejecutar si se ha producido otro posible error
End Try
Pg. 162
Aplicaciones Mdi
Una aplicacin de tipo o estilo MDI (Multiple Document Interface), Interfaz de
Documento Mltiple, se compone de un formulario principal, tambin denominado formulario
MDI, que actuar como contenedor de otros formularios (documentos) abiertos durante el
transcurso del programa, denominados formularios hijos o secundarios MDI. Como ejemplos de
este tipo de aplicacin tenemos PowerPoint o Access.
A diferencia de lo que ocurra en versiones anteriores de VB, un formulario MDI admite los
mismos controles que un formulario normal, aunque dada su orientacin de formulario
contenedor, se recomienda limitar los controles en un MDI a los estrictamente necesarios. El
men es el ejemplo ms identificativo de control idneo para un formulario MDI, ya que a
travs de sus opciones, podremos abrir los formularios hijos de la aplicacin.
La base de una Aplicacin con Interfaz de mltiples documentos (MDI) ser el formulario
primario MDI que contiene las "subventanas" MDI secundarias, dentro de las cuales los
usuarios interactan con la aplicacin.
Pg. 163
Pero cmo conseguimos tener varias copias de un mismo tipo de formulario, en nuestro
caso llamado frmSecundario? Observa las siguientes instrucciones:
Me.IsMdiContainer = True ' Esto se puede hacer en tiempo de diseo, en el
frmMdi_Load, .... Aqu le indicamos que el actual es MDI contenedor, es decir,
que puede contener formularios como subventanas.
frm.MdiParent = Me ' Para indicar que es hijo del actual. Si fuese hijo de
otro pondramos frm.MdiParent = frmPrin
frm.rutaFichero = fichero ' rutaFichero es una variable Public que tiene la
clase frmSecundario. As cada formualario creado de esta clase lo contendr.
frm.Text = nomFichero ' ttulo que se ver en la nueva ventana
Try
frm.picImagen.Image = Image.FromFile(fichero) ' Carga el fichero en el control
picImagen del creado. Esto tambin se podra hacer en el evento Load del
frmSecundario
'frm.picImagen.Image = New System.Drawing.Bitmap(fichero)
frm.Show() ' Lo muestra en pantalla, en este caso "dentro" del MDI
Catch ex As Exception
frm.Close() ' Debemos eliminarlo (cerrarlo) ya que se ha producido un error y
no queremos que aparezca, ya que en este caso ya se haba aadido a la coleccin
MdiChildren
MessageBox.Show("Error en fichero '" & nomFichero & "'" &
Me.MdiChildren.Count, "Atencin", MessageBoxButtons.OK,
MessageBoxIcon.Exclamation)
End Try
Pg. 164
O lo que es lo mismo:
Pg. 165
TryCast(Me.ActiveMdiChild, frmSecundario).picImagen.BackgroundImage =
Image.FromFile(fichero)
Para conseguir que bajo una opcin de men se muestre la lista de ventanas abiertas
usaremos la propiedad MdiWindowListItem del MenuStrip (asignndole el
ToolStripMenuItem correspondiente).
En el siguiente ejemplo tendramos las ventanas en Cascada. Observa que bajo la opcin
Ventana aparecen las abiertas y marcadas la 3, ya que esta es la activa en este momento. Es
decir, el ToolStripMenuItem al que le hemos aplicado la propiedad MdiWindowListItem es al
de ttulo Ventana.
Ejemplo, supongamos que queremos recorrerlos todos y hacer distintas cosas dependiendo
del tipo de formulario que sea:
Pg. 166
For Each frm As Form In My.Application.OpenForms ' Recorre todos los formularios
abiertos, incluso el actual
Select Case frm.GetType.Name
Case "frmSegundo"
' Instrucciones si es de este tipo
Case "frmAyuda"
' En el caso de que sea de este otro
Case "frmPrincipal"
' Tercera posibilidad
End Select
Next
Pg. 167