Вы находитесь на странице: 1из 251

Introduccin:

La programacin orientada a objetos (POO) nos permite escribir cdigo menos propenso a fallos adems de permitirnos la reutilizacin de cdigo de forma ms conveniente. En este artculo veremos las caractersticas de la POO desde el punto de vista de los lenguajes de .NET Framework y cmo utilizar los distintos elementos que nos permitirn crear cdigo que sea ms fcil de escribir y mantener.

LA PROGRAMACIN ORIENTADA A OBJETOS


En Todo Programacin existe una seccin denominada Cuadernos de Principiantes donde se estudia algoritmia y estructuras de datos a nivel iniciacin. Est planificado que se estudie a nivel terico la programacin orientada a objetos, por tanto para aquellos que no tengis nocin alguna sobre POO mejor guarda a buen recaudo este nmero de TP y espera a aprender los conceptos tericos necesarios para luego aplicarlos en el marco, nunca mejor dicho, de .NET.

LOS PILARES DE LA POO


Recordemos que tres son las principales caractersticas de un lenguaje orientado a objetos, es decir, se considera que un lenguaje est totalmente orientado a objetos si es capaz de proveer estas tres caractersticas: Encapsulacin Herencia Polimorfismo

Veamos una pequea descripcin de cada una de ellas y despus las ampliaremos para comprender mejor su significado y cmo puede ayudarnos a crear aplicaciones que aprovechen todas las posibilidades que nos da la POO. La ENCAPSULACIN es la cualidad de unificar los datos y la forma de manipularlos, de esta forma podemos ocultar el funcionamiento de una clase y exponer solo los datos que manipula (mediante propiedades), as como proveer de medios para poder manipular dichos datos (mediante mtodos). De esta forma solo exponemos al mundo exterior la informacin y la forma de manipularla, ocultando los detalles usados para manejar esos datos y, lo que es ms importante, evitando que nadie manipule de una forma no controlada dicha informacin. La HERENCIA es la cualidad de poder crear nuevas clases (o tipos) basadas en otras clases, de forma que la nueva clase obtenga todas las caractersticas de la clase que ha heredado, tanto los datos que contiene como la forma de manipularlos, pudiendo aadir nuevas caractersticas e incluso cambiar el comportamiento de algunas de las incluidas en la clase base, (siempre que as se haya previsto). Mediante la herencia podemos crear de forma fcil una jerarqua

de clases que comparten un mismo comportamiento bsico pero que cada nueva generacin puede tener (y de hecho tiene) un nuevo comportamiento. El POLIMORFISMO es la cualidad de implementar de forma particular algunas de las caractersticas que tienen las clases, de forma que cuando necesitemos usarlas no nos preocupe la implementacin interna que cada una tenga, lo que realmente nos interesa o nos debe importar es que podemos usar esas caractersticas e incluso podamos acceder a ellas de forma annima... o casi.

OTROS CONCEPTOS DE LA POO


Tal como tendrs oportunidad de ver en los Cuadernos de Principiantes y lo indicado en el cuadro Los pilares de la POO, la POO se basa en tres caractersticas que son comunes a todos los lenguajes orientados a objetos, pero si tenemos esas caractersticas y no sabemos cmo aplicarlas, la verdad es que no nos ser de mucha utilidad. Pero antes de ver algo de cdigo concreto, creo que es importante que aprendamos otros conceptos relacionados tambin con la POO, pero esta vez desde un punto de vista del programador, es decir, vamos a dejar en parte la teora y vamos a ser algo ms prcticos, ya que los siguientes conceptos sern con los que tendremos que "bregar" a diario. Adems nos interesa conocerlos para aprovechar lo que un lenguaje de programacin orientado a objetos nos ofrece, si bien, es posible que, al menos de forma genrica, no todos los lenguajes dispongan de ellos. Por eso, aunque lo que se ha dicho y se diga a continuacin ser vlido para cualquier lenguaje orientado a objetos, lo vamos a enfocar desde el punto de vista de .NET Framework, ms concretamente desde el punto de vista del programador de Visual Basic .NET y C#.

LAS CLASES Y ESTRUCTURAS


Como hemos estado mencionando, en los lenguajes orientados a objetos, existe el concepto clase. Cuando hablamos de clases, tambin podemos extenderlo a estructuras, de hecho, para los programadores de C++ una clase no es ms que una estructura que se comporta de forma diferente. Una clase es una pieza de cdigo en la que podemos definir una serie de datos y al mismo tiempo unos mtodos (funciones o procedimientos) que nos permitirn acceder a esos datos. Cuando definimos una clase, lo que estamos haciendo es definir una plantilla, a partir de la cual podemos crear objetos en la memoria. Por tanto, la clase es el molde con el cual podemos crear nuevos objetos. Para poder crear algo "tangible" a partir de una clase, tenemos que crear en la memoria un nuevo objeto del tipo de la clase, en estos casos lo que decimos es que instanciamos un nuevo objeto de la clase. A partir de ese momento tendremos algo real con lo que podemos trabajar: una instancia de la clase, es decir, la definicin realizada en la clase se ha convertido en un objeto al que podemos acceder y que podemos empezar a utilizar, dndole nuevos valores a los datos que manipula y usando las funciones que nos permiten manipular dichos datos.

La diferencia principal entre una clase y una estructura es la forma en que se crean los objetos que representan a esas "ideas". Los objetos creados a partir de las clases son objetos por referencia, es decir, si declaramos una variable para manipular ese objeto, lo que tendremos ser una referencia (o puntero) a una direccin de memoria en la que realmente est el objeto. Mientras que los objetos creados a partir de una estructura se almacenan de forma diferente, en lugar de "apuntar" a una direccin de memoria en la que se encuentra el objeto, es como si las variables declaradas como estructuras fuesen realmente el objeto permitindonos hacer ciertas operaciones y manipulaciones que los objetos obtenidos a partir de una clase no pueden realizar de la misma forma. Esto lo veremos despus con ms detalle.

NOTA: Clases En .NET siempre usamos una clase para escribir cualquier tipo de cdigo. Por tanto, hagamos lo que hagamos en .NET Framework, debemos hacerlo dentro de una clase. Esto no quiere decir que siempre tengamos que usar las caractersticas de la POO, ya que si simplemente queremos hacer una aplicacin que muestre un mensaje en la consola, el cdigo no tiene porqu usar la herencia, el polimorfismo o la encapsulacin, simplemente escribimos el cdigo que muestre el mensaje y asunto arreglado, pero lo que si podremos hacer es usar algunas de las "otras" ventajas que nos aporta la programacin orienta a objetos.

INTERFACES
Cuando hablamos de polimorfismo, ineludiblemente tenemos que hablar de las interfaces, ya que, principalmente, nos posibilita utilizar esta caracterstica de la POO. La pregunta es: qu es una interfaz? Aqu no hablamos de "interfaces de usuario", es decir, lo que se mostrar al usuario de nuestra aplicacin, sino a una clase especial en la que solamente se definen los mtodos y propiedades que una clase que la implemente debe codificar. Las interfaces representan un contrato, de forma que cualquier clase que la implemente debe utilizar los miembros de la interfaz usando la misma forma en que sta la ha descrito: mismo nmero de argumentos, mismo tipo de datos devuelto, etc. Gracias a la implementacin de interfaces podemos crear relaciones entre clases que no estn derivadas de la misma clase base, pero que tengan mtodos comunes, al menos en la forma, aunque no necesariamente en el fondo. Anteriormente usamos el ejemplo del mtodo Guardar, este mtodo se puede definir en una interfaz, las clases que quieran implementar un mtodo Guardar "estandarizado" firmarn un contrato con la interfaz que lo especifica, aunque la forma interna de funcionamiento solo atae al programador de la clase, lo importante es saber que cualquier clase que haya firmado ese contrato tendr que seguir las condiciones impuestas por la interfaz, de esta forma todas las clases tendrn un mtodo Guardar "compatible", aunque, tal como mostramos antes, cmo se realice esa accin de guardar no debe preocuparnos, simplemente nos fiaremos de que se ha implementado adecuadamente para almacenar los datos que la clase manipula.

NOTA: HERENCIA MLTIPLE Y HERENCIA SIMPLE En C++ y algunos otros lenguajes orientados a objetos se permiten la herencia mltiple, es decir, una clase se puede derivar de varias clases a la vez. Los lenguajes de .NET Framework, usan lo que se denomina herencia simple, es decir, una clase solo se puede derivarse directamente de otra clase, si bien se permite implementar mltiples interfaces. Pero debido a cmo funciona la herencia, cualquier clase derivada a partir de otra, heredar indirectamente todas las clases e interfaces que la clase base haya heredado o declarado. Adems, en .NET, todas las clases siempre se derivan de la clase base Object que es la clase que est en la parte superior de la jerarqua de clases.

CONSTRUCTORES Y DESTRUCTORES, EL PUNTO DE INICIO Y FINAL DE LAS CLASES


Cuando creamos un objeto a partir de una clase, se sigue un proceso, el cual empieza en el momento en que decidimos crear una nueva instancia de dicha clase. En estos casos, el compilador utiliza lo que se llama el constructor de la clase. Siempre que se crea un nuevo objeto en la memoria est involucrado el constructor de la clase. Los constructores son procedimientos especiales (funciones que no devuelven un valor) en los que podemos escribir toda la lgica que debe usarse para la correcta creacin del objeto. Por ejemplo, podemos inicializar las variables usadas, podemos asignarle algunos valores predeterminados, etc. De igual forma, cuando un objeto ya no se necesita ms, se destruye mediante una llamada al destructor de la clase. En .NET la destruccin de los objetos suele hacerse de forma automatizada, es decir, a diferencia de lo que ocurre en otros entornos de programacin, no es necesario destruir explcitamente un objeto para eliminarlo de la memoria, esa gestin de limpieza de objetos la realiza el recolector de basura (Garbage Collector, GC) de .NET, el cual decide cuando un objeto no se necesita ms y en ese caso lo elimina dejando libre la memoria utilizada para otros menesteres.

SOBRECARGA (OVERLOAD)
Una de las caractersticas que tambin nos ofrece los lenguajes orientados a objetos es la posibilidad de definir varias funciones de las clases con un mismo nombre, de esta forma, podremos crear versiones diferentes, por ejemplo para que reciban argumentos de distintos tipos sin necesidad de cambiarle el nombre. Supongamos que queremos hacer una funcin que realice cualquier tipo de operacin sobre dos valores numricos, sera lgico pensar que si esos valores son de tipo entero, el resultado que devuelva la funcin tambin debera ser de tipo entero, en caso de que los valores a usar en la operacin son de tipo flotante, el resultado podra devolverlo de ese mismo tipo.

En los lenguajes no orientado a objetos, tendramos que crear dos funciones con nombres diferentes, por ejemplo: sumaInt y sumaFloat. Pero la sobrecarga nos permite crear dos funciones que se llamen suma y el compilador utilizar la adecuada segn el tipo de datos que pasemos como argumentos. El nico requisito para poder crear sobrecargas de mtodos es que las diferentes versiones se diferencien en los argumentos, ya sea porque sean de diferentes tipos de datos o porque el nmero de argumentos usados sea diferente, de esa forma el compilador no tendr ningn problema en saber cual debe usar en cada ocasin. La sobrecarga la podemos aplicar tanto a los constructores como a cualquier otro mtodo de la clase.

NOTA: Sobrecarga No existir la posibilidad de crear mtodos sobrecargados si solamente se diferencian en el tipo de datos devuelto, ya que en esos casos el compilador no podr decidir correctamente qu mtodo debe utilizar.

LOS MIEMBROS DE LAS CLASES: CAMPOS, PROPIEDADES Y MTODOS


Como hemos comentado, las clases manejan datos y proveen de funciones para acceder a esos datos. Para ser precisos, los datos se mantienen o almacenan internamente en los campos declarados en las clases. Los campos no son otra cosa que variables declaradas en la clase, habitualmente declaradas de forma privada. Por qu declaradas de forma privada? Precisamente para seguir o cumplir la caracterstica de encapsulacin de la POO, es decir, los datos no deben exponerse de forma directa. Si queremos exponer los datos, podemos usar las propiedades. Las propiedades son funciones especiales que nos permiten acceder a esos datos, aunque para ser ms precisos, las propiedades realmente representan a los datos que una clase contiene, al menos de forma pblica. De esa forma podemos "controlar" la forma en que se leen o asignan esos datos, ya que las propiedades realmente son funciones en las que podemos escribir cdigo para controlar los valores asignados o ledos. Los mtodos nos permitirn realizar acciones sobre los datos, por ejemplo devolver un rango de valores o simplemente una representacin amigable de la informacin contenida. Debido a que algunas veces los mtodos devolvern algo y otras no, podemos usar tanto funciones que devuelvan o no un valor.

NOTA: Mtodos En C# los mtodos siempre son funciones, que devolvern un tipo concreto o el valor especial void, que se usa para indicar que una funcin no devolver ningn valor. En Visual Basic .NET existen dos tipos de mtodos distintos, las funciones (Function) que siempre devuelven un valor y los procedimientos (Sub) que no devuelven ningn valor.

Adems de los campos, mtodos y propiedades, las clases tienen otros miembros como los eventos y las enumeraciones. stos nos permitirn recibir notificaciones de cuando algo ocurra (eventos) o declarar ciertos valores constantes que podemos usar para restringir algunos valores asignados a las propiedades o que nos permitan seleccionar de forma coherente la informacin que queremos obtener (enumeraciones).

EL MBITO DE LOS MIEMBROS DE LAS CLASES


Las buenas formas de trabajar con las clases nos indican que los campos deberan ser privados, con idea de que no estn accesibles de forma externa. Por supuesto tambin podemos definir otros miembros de las clases de forma privada, esto es til cuando la funcionalidad es para uso exclusivo de otros miembros de la clase. Pero cuando queremos exponer la funcionalidad fuera de la clase podemos hacerla de varias formas, aqu es donde entran en juego el mbito de los miembros de las clases. El mbito lo aplicamos para permitir el acceso desde cualquier cdigo fuera de la clase o para restringir ese acceso. Dependiendo de cmo queramos que se acceda a los miembros de la clase podemos usar distintos modificadores de mbito. Veamos los que podemos usar y cuando y porqu usarlos. La instruccin entre parntesis ser la que tendremos que usar en C#. Private (private). Para uso privado. Cuando declaramos un miembro como privado slo lo podremos acceder desde la propia clase. Este es el ms restrictivo y el que se recomienda para los campos y las funciones de uso interno. Protected (protected). Uso protegido. Los elementos declarados como protegidos slo estarn accesibles, adems de en la propia clase, por cualquier clase derivada. Friend (internal). Para uso dentro de la propia aplicacin. Cuando declaramos un miembro con este modificador, solo podremos acceder a l desde la propia clase o desde cualquier cdigo que se encuentre en el mismo ensamblado (proyecto). Protected Friend (protected internal). Una mezcla de Protected y Friend, es decir solo accesible desde las clases derivadas o desde el mismo proyecto. Public (public). Este modificador de mbito nos permite exponer pblicamente cualquier miembro de la clase, de forma que no haya restricciones para acceder a l.

NOTA: mbito Los miembros de una clase los podemos declarar sin especificar el mbito, dependiendo del lenguaje de programacin que usemos se aplicar un modificador de mbito u otro. En C#, si no indicamos el mbito, las declaraciones se consideran privadas, mientras que en Visual Basic .NET el mbito predeterminado es Friend.

MIEMBROS VIRTUALES, NO REEMPLAZABLES Y ABSTRACTOS


Para ir terminando la parte "terica" sobre la programacin orientada a objetos, veamos cmo podemos darle un significado distinto a los miembros de una clase, dependiendo de cmo queramos que se comporten y por extensin cmo podemos utilizarlos tanto en la propia clase como en las clases derivadas. Como hemos comentado, cuando una clase hereda a otra podemos modificar el comportamiento de los miembros heredados, pero estos solamente se podrn modificar si la clase base as lo contempla o lo permite. De forma predeterminada, al menos en .NET, cuando declaramos un mtodo o una propiedad en una clase, solo podremos acceder a l desde una instancia creada (un objeto) en memoria, desde donde podemos usarlos depender del mbito que le hayamos aplicado. De igual forma, el que una clase que se base en otra, pueda crear su propia versin de ese mtodo o propiedad depender de que la clase base lo haya declarado como virtual (Overridable en VB .NET). Los mtodos virtuales sern los que podamos sobrescribir en las clases derivadas, de forma que podamos crear nuestras propias versiones. En .NET los miembros de una clase no son virtuales de forma predeterminada. Por tanto, si queremos que la clase derivada pueda crear su propia versin de un mtodo, debemos declararlo como virtual o "redefinible". Si en una clase base hemos definido un mtodo virtual, pero posteriormente queremos que no se pueda seguir redefiniendo en otras clases derivadas, debemos indicarlo usando el modificador NotOverridable, el cual se usar junto con Overrides, ya que sobrescribe un miembro de la clase base y como adems lo queremos marcar como no virtual, debemos usar las dos instrucciones: Overrides NotOverridable, (en C# se indicar con override sealed). Pero tambin se nos puede presentar el caso contrario, en el que queremos que un mtodo forzosamente haya que redefinirlo en las clases derivadas, en esos casos la clase base que lo define no incluye ninguna implementacin, es decir, el mtodo no contiene cdigo ejecutable, solo la definicin, (como ocurre con las interfaces). Se dice que estos mtodos son abstractos porque solo se ha definido en la forma y no se ha implementado ningn cdigo ejecutable. En Visual Basic se definen usando el modificador MustOverride (asbtract en C#). Estos mtodos abstractos solo se pueden declarar en clases abstractas (MustInherit en Visual Basic, abstract en C#) y por la necesidad de tener que redefinirlos, son implcitamente virtuales. Las instrucciones o modificadores que nos permiten crear estos tipos de miembros son:

Overridable (virtual). Los miembros virtuales son los que las clases derivadas puedes sobrescribir para crear su propia versin. Para indicar en una clase derivada que estamos sobrescribiendo dicho elemento, usaremos Overrides (override en C#). NotOverridable (sealed). Los miembros virtuales heredados se pueden marcar como no virtuales, (las siguientes clases derivadas no podrn sobrescribirlos), usando esta instruccin a continuacin de Overrides (override). MustOverride (abstract). Un mtodo que se debe reemplazar en la clase derivada y que solo se define en la clase base sin ningn cdigo ejecutable. Los mtodos abstractos son virtuales por defecto y solo se pueden declarar en clases abstractas.

MIEMBROS DE INSTANCIAS Y COMPARTIDOS


En todos estos casos, los miembros de la clase siempre son miembros de instancia, es decir, solo existen en la memoria cuando se crea un nuevo objeto (se crea una nueva instancia). Pero es posible que nos interese crear miembros compartidos, es decir, miembros que pertenecen a la propia clase, no a ninguna instancia en particular. Dndonos la oportunidad de poder acceder siempre a ellos, independientemente de que hayamos creado o no un nuevo objeto en la memoria. En estos casos decimos que creamos miembros compartidos (estticos en el argot de C#/C++), esta diferencia de "nomenclatura" dependiendo del lenguaje de programacin, es porque para definir un miembro perteneciente a la clase y no a una instancia en particular, usaremos en Visual Basic la instruccin Shared (compartido), mientras que en C# se usar la instruccin static (esttico). Resumiendo, Shared (static), declara un miembro compartido, los miembros compartidos no pertenecen a ninguna instancia en particular y solamente pueden acceder a campos u otros miembros tambin compartidos. Desde los miembros de instancia podemos acceder tanto a miembros compartidos como de instancia.

NOTA: STATIC En Visual Basic existe tambin la instruccin Static, (que no tiene equivalencia en C#), en este caso se utiliza con variables declaradas en un procedimiento y sirven para indicar que esa variable debe mantener el valor entre distintas llamadas a dicho procedimiento, a diferencia del resto de variables que solo existen mientras se ejecuta el cdigo del procedimiento y cuyos valores se pierden al finaliza la ejecucin del mismo.

CLASES ABSTRACTAS Y SELLADAS


De igual forma que podemos modificar el comportamiento de los miembros de una clase, tambin podemos cambiar el comportamiento predeterminado de las clases. Como hemos comentado, las clases de .NET pueden usarse para crear nuevas clases derivadas de ellas, esta es la funcionalidad predeterminada, pero no obligatoria, es decir, si queremos podemos usar una clase por si misma o como base de otras. Pero tambin podemos hacer que una clase solamente se use como clase base de otras, pero no se puedan usar para crear nuevas instancias en memoria, este es el caso de las clases abstractas. Una clase abstracta puede contener miembros abstractos, miembros normales o virtuales. Para indicar que una clase es abstracta, se usa el modificador MustInherit en Visual Basic o abstract en C#. La contrapartida de las clases abstractas son las clases selladas o clases que no se pueden usar como clases base, en estos casos las clases las definiremos como NotInheritable en Visual Basic o sealed en C#. Como es lgico, las clases no heredables se pueden usar en ocasiones en las que no nos interese que nadie cambie el comportamiento que tiene, por tanto no se podrn declarar miembros virtuales ni abstractos, ya que no tendra ningn sentido. Las estructuras siempre son "clases selladas", (aunque no se use un modificador para indicarlo), por tanto, no podemos usarlas como base de otras.

Conclusiones
En la segunda parte de esta serie dedicada a la programacin orientada a objetos veremos cmo poner en prctica todo lo que hemos comentado, adems de ver otras peculiaridades de la POO, tales como la definicin de interfaces y cmo implementarlas, ocasin que tambin aprovecharemos para ver de forma prctica cmo usar el polimorfismo y la herencia en los lenguajes de .NET.

Programacin Orientada a Objetos en .NET (2) Conceptos prcticos


Publicado el 13/Dic/2006 Actualizado el 13/Dic/2006 Autor: Guillermo 'guille' Som
Importante: Este artculo est registrado por Iberprensa (Studio Press) y est prohibida la reproduccin total o parcial incluso indicando la procedencia.

En esta ocasin veremos con ejemplos prcticos cmo utilizar las caractersticas de la POO usando lenguajes de .NET, de forma que tengamos claro cmo usar la herencia, el polimorfismo y la encapsulacin, pero con cdigo. Versin originalmente publicada en Todo Programacin nmero 7 (Oct 2004)

Introduccin:
En el artculo anterior vimos algunos conceptos tericos de la POO (Programacin Orientada a Objetos) desde el punto de vista de los lenguajes de .NET Framework, en esta ocasin veremos con ejemplos prcticos cmo utilizar las caractersticas de la POO en Visual Basic .NET, (en el ZIP se incluye tambin el cdigo para C#), de forma que tengamos claro cmo usar la herencia, el polimorfismo y la encapsulacin, pero con cdigo.

VISUAL BASIC .NET Y LA POO


Tal como comentamos en el artculo anterior, uno de los pilares de la POO es la herencia. Mediante la herencia podemos definir clases totalmente operativas y crear nuevas clases basadas en ellas de forma que hereden toda la funcionalidad de la clase base y nos permita ampliarla. Por tanto, vamos a empezar viendo cmo definir una clase y cmo aplicar en Visual Basic .NET el resto de conceptos relacionados con la programacin orientada a objetos.

Nota: Este artculo se public en Octubre de 2004, y por tanto todo lo aqu explicado est relacionado con la versin 1.1 de .NET Framework. La versin de .NET Framework que hay actualmente (a la hora de escribir esta nota) es la 3.0, (que en el fondo es la misma que la 2.0), y se han introducido ciertos cambios o mejoras, pero bsicamente lo aqu explicado sigue siendo tan vlido ahora como hace dos aos.

DEFINIR CLASES EN VISUAL BASIC .NET


Antes de poder usar las caractersticas de la POO tendremos primero que aprender a declarar una clase. La declaracin de una clase se define usando la instruccin Class seguida del nombre de la clase y termina

usando las instrucciones End Class. Dentro de ese bloque definiremos los campos, propiedades y mtodos que queramos que tenga la clase.

NOTA: En Visual Basic .NET la definicin de una clase se puede hacer en cualquier fichero de cdigo (con extensin .vb), aunque no es obligatorio hacerlo en un fichero independiente como ocurra con las versiones anteriores, es recomendable hacerlo, para que nos resulte ms fcil de mantener.

Public Class A Private _prop2 As Integer Private _prop1 As String ' Public Property Prop1() As String Get Return _prop1 End Get Set(ByVal value As String) If value <> "" Then _prop1 = value End If End Set End Property Public Property Prop2() As Integer Get Return _prop2 End Get Set(ByVal value As Integer) _prop2 = value End Set End Property ' Public Sub Mostrar() Console.WriteLine("{0}, {1}", _prop1, _prop2) End Sub End Class

Listado 1 Tal como podemos ver en el listado 1, tenemos una clase llamada A que define dos campos, dos propiedades y

un mtodo. Los dos campos, declarados como privados, se usan para mantener "internamente" la informacin que se expone mediante las dos propiedades pblicas, de esta forma protegemos los datos y esta sera una forma de encapsular la informacin. De las dos propiedades definidas para acceder a esos datos, solo la propiedad Prop1 hace una comprobacin de que no se asigne una cadena vaca al campo que mantiene internamente la informacin, aunque en este ejemplo por su simplicidad no hacemos ms comprobaciones, en una clase algo ms compleja, se podran realizar otras comprobaciones, por ejemplo si el valor a almacenar es una cuenta de email, podramos comprobar que es una cadena correctamente formada. Las propiedades suelen definir dos bloques de cdigo, uno, el bloque Get se utiliza cuando queremos acceder al valor devuelto por la propiedad, el otro es el bloque Set, el cual se utilizar cuando asignemos un valor a la propiedad. El mtodo Mostrar se usar para mostrar el contenido de las dos propiedades por la consola y est definido como Sub (void en C#) porque no devuelve ningn valor.

SOBRESCRIBIR MIEMBROS HEREDADOS


Tal como comentamos en el artculo anterior, todas las clases de .NET se derivan directa o indirectamente de la clase Object. La clase definida en el listado 1 tambin se deriva de Object aunque no se indique expresamente. La clase base de todas las clases de .NET tiene un mtodo que se utiliza para recuperar informacin, (en formato cadena), del contenido de la clase: el mtodo ToString. Cada clase puede crear su propia versin del mtodo ToString para que devuelva una representacin adecuada, por ejemplo los tipos numricos devuelven una cadena que representa al nmero que contiene. En nuestra clase podemos redefinirlo para que nos devuelva el contenido de los dos datos que la clase mantiene:
Public Overrides Function ToString() As String Return String.Format("{0}, {1}", _prop1, _prop2) End Function

Para indicarle al compilador que estamos redefiniendo un mtodo ya existente, lo indicamos con la instruccin Overrides (override en C#). Debido a que ahora nuestra clase tiene una nueva versin de este mtodo, cualquier clase que se derive de ella tambin heredar la nueva implementacin del mtodo ToString.

USAR LA HERENCIA EN VISUAL BASIC .NET


La clase que hemos definido en el listado 1 no indicaba de ninguna forma que se deriva de la clase Object, este es un caso excepcional, ya que todas las clases de .NET se derivan de forma "automtica" de la clase Object. Para indicar en Visual Basic .NET que una clase se deriva de otra, debemos usar la instruccin (o palabra clave) Inherits seguida de la clase que queremos usar como base. Esa instruccin tiene que indicarse al principio de la declaracin de la clase, antes que cualquier otra instruccin, con excepcin de los comentarios.

Para crear una clase que se derive de la clase A definida en el listado 1, tendramos que hacer lo siguiente:
Public Class B Inherits A End Class

Tal como podemos comprobar, la clase B no define ningn mtodo ni propiedad, pero realmente si que tiene mtodos y propiedades: todos los que tenga la clase A (adems de los de la clase Object). Para comprobarlo podemos definir una variable del tipo de la clase B y comprobaremos que esta clase tiene los mismos miembros que la clase A, tal como se muestra en el listado 2.
Sub Main() Dim objB As New B

objB.Prop1 = "guille" objB.Prop2 = 47

objB.Mostrar() Console.WriteLine("{0}", objB.ToString) End Sub

Listado 2

OCULTAR MIEMBROS HEREDADOS


Todo funciona como esperbamos, aunque hay un pequeo problema, si quisiramos modificar el comportamiento de los miembros heredados por la clase B, no podramos hacerlo. La razn es bien simple: la clase A no ha definido los miembros como virtuales (o reemplazables). Por tanto no se pueden crear nuevas versiones de los mismos en la clase B, o casi... Realmente la clase B si que puede definir nuevas versiones de los miembros que tiene la clase A, al menos puede crear mtodos y propiedades que tengan el mismo nombre, por ejemplo:
Public Sub Mostrar() Console.WriteLine("Mostrar en la clase B: {0}, {1}", Prop1, Prop2) End Sub

Esto es totalmente correcto, al menos en el sentido de que no produce ningn error; lo ms que producir esa declaracin es una advertencia del compilador indicndonos que ese mtodo entra en conflicto con el definido en la clase base A, tal como podemos comprobar en la figura 1.

Figura 1. Advertencia de ocultacin Esa advertencia nos informa que deberamos indicar que la declaracin "oculta" a la definida en la clase A y por tanto deberamos usar la instruccin Shadows (new en C#). Aunque usemos Shadows, el problema real sigue existiendo: el mtodo declarado en la clase B oculta al declarado (y heredado) en la clase A. Si despus de definir este mtodo de la clase B volvemos a ejecutar el cdigo del listado 2, comprobaremos que se utiliza el nuevo mtodo. Posiblemente el lector pensar que eso es lo que queramos conseguir: tener nuestra propia versin del mtodo Mostrar. Es ms, si definimos una nueva clase que se derive de B podemos comprobar que realmente es ese mtodo el que se hereda por la nueva clase. En el listado 3 podemos ver la definicin de la clase C y el cdigo para comprobar lo que mostrara:
Public Class C Inherits B End Class

Sub Main() Dim objC As New C

objC.Prop1 = "guille" objC.Prop2 = 47

objC.Mostrar() Console.WriteLine("{0}", objC.ToString) End Sub

Listado 3 Y lo que imprime es exactamente lo mismo que usando la clase B. Por tanto, el objetivo est conseguido, es decir, la clase B ha "redefinido" un mtodo de la clase A y esa nueva versin es la que se usar a partir de ese momento por las clases que se basen en la clase B. Aparentemente as es. Al menos si lo tomamos al pie de la letra. El nico problema es que acabamos de romper una de las cualidades de la programacin orientada a objetos:

el polimorfismo. Esta nueva definicin del mtodo Mostrar ya no tiene nada que ver con la definida por la clase A y por tanto no existe ninguna relacin "polimrfica" entre ambos mtodos. Para ser ms precisos, tanto la clase B como la clase C tienen dos definiciones del mtodo Mostrar: el inicialmente heredado de la clase A y el nuevo definido por la clase B, aunque siempre prevalecer el definido expresamente en la clase derivada frente al heredado de la clase base. Si pudisemos ver el objeto creado en la memoria a partir de la clase B (e incluso de la clase C), nos daramos cuenta de que realmente est dividido en tres partes, tal como se muestra en la figura 2: 1. La parte heredada de la clase Object 2. La parte heredada de la clase A 3. Las definiciones propias de la clase B

Figura 2. Objeto B en memoria El mtodo ToString definido en Object ha sido reemplazado o, para que lo comprendamos mejor, sustituido por el redefinido en la clase A, pero el mtodo Mostrar de la clase A an existe, lo que ocurre es que ha sido ocultado por el que se ha definido en la clase B. Para demostrar que es as, que existen dos mtodos Mostrar en la memoria, podemos utilizar el polimorfismo para "extraer" el mtodo Mostrar que est oculto. Para ello tendremos que declarar una variable del tipo de la clase A y decirle que extraiga del objeto B la parte que le corresponde: solo la parte definida en la clase A. Esto se consigue de una forma muy simple: asignando a una variable del tipo A el contenido de la variable que

apunta al objeto B:
Dim objA As A objA = objB

A partir de este momento el objeto B est siendo referenciado por el objeto A, pero, y esto es importante, solo la parte que A conoce, es decir, la variable objA solamente podr acceder al "trozo" del objeto B que se deriv de la clase A. Por tanto, si llamamos al mtodo Mostrar de la variable objA, accederemos al mtodo Mostrar que el objeto B contiene porque la consigui al derivarse de A. S, esto es algo complicado y que no es fcil de comprender, pero es importante intentar asimilarlo, ya que es muy probable que lo necesitemos en nuestros proyectos, sobre todo si sabemos que se puede hacer. Adems de que esta sera la nica forma que tenemos de acceder a ese mtodo "oculto", ya que cualquier intento de acceder al mtodo Mostrar mediante un objeto del tipo B, siempre acceder al definido en la propia clase B y que oculta al heredado de la clase A.

NOTA: Cuando declaramos una variable y la instanciamos, (creando un nuevo objeto a partir de una clase), dicha variable simplemente tiene una referencia al objeto creado en la memoria, (la variable simplemente tiene un puntero al objeto real), por tanto, ese objeto existe y puede ser referenciado por otras variables, aunque esas otras variables deben ser de tipos "incluidos" en la clase usada para crear dicho objeto. Al instanciar un nuevo objeto del tipo B, (tal como se muestra en la figura 2), podemos acceder a l mediante variables de tipo Object, de tipo A y, por supuesto, de tipo B.

INDICAR LOS MIEMBROS VIRTUALES


Como hemos comprobado, si queremos que los miembros de nuestra clase se puedan redefinir en clases derivadas, debemos indicarlo de forma expresa. Para que esto sea as, utilizaremos la instruccin Overridable (virtual en C#). De esta forma le indicaremos al compilador que el mtodo se puede redefinir, es decir, que en la clase derivada se puede crear una nueva versin "personalizada" de dicho miembro. Con esto logramos que en sucesivas derivaciones de la clase solamente exista un mismo miembro polimrfico. La ventaja principal es que si en otra clase decidimos crear una nueva versin de, por ejemplo, un mtodo, cuando se cree un objeto en la memoria, solo existir ese mtodo, no varios mtodos con el mismo nombre, pero sin ninguna relacin entre ellos, exceptuando el hecho de que se llamen de la misma forma. Tal como vimos en la seccin SOBRESCRIBIR MIEMBROS HEREDADOS, tendremos que usar la instruccin Overrides (override en C#), para indicar que nuestra intencin es crear una versin propia de uno de los miembros heredados. Pero no solo basta con usar esa instruccin, ya que si queremos redefinir un miembro existente en alguna de las clases que hemos heredado, la "firma" de nuestra versin debe ser la misma que el original. Es decir, si es un mtodo que devuelve una cadena y no recibe parmetros, debemos "respetar" esas mismas caractersticas, porque de lo que se trata es de cumplir con un contrato, dicho contrato estipula que tipo de miembro es, (un mtodo o una propiedad), que tipo de datos devuelve, si recibe o no parmetros y en caso de que los reciba de

que tipo deben ser. Todo esto es para garantizar que esos miembros se puedan usar de forma independiente de la clase en el que se ha declarado, con idea de que podamos acceder a ellos mediante objetos de las clases que se han usado para crear la nueva, (las clases de las que se deriva la clase que sobrescribe el mtodo). Por ejemplo, si el mtodo Mostrar definido en la clase A se hubiese declarado como virtual, (Overridable), y en la clase B lo hubisemos redefinido usando la instruccin Overrides, podramos acceder a dicho mtodo (de un objeto creado a partir de la clase B) usando tanto una variable de la clase A como una de la clase B; ya que en la memoria solamente existir un mtodo llamado Mostrar. A diferencia de lo que ocurra antes (al no declararlo como virtual), que realmente existan dos mtodos Mostrar.

DEFINIENDO INTERFACES
Una interfaz realmente es la definicin de los miembros pblicos de una clase. Pero en los lenguajes de programacin de .NET tambin podemos definir clases especiales que simplemente definan cmo deben ser los miembros que una clase implemente. Es decir que caractersticas deben tener. De esta forma podemos garantizar que si varias clases implementan los miembros definidos en una interfaz, podemos usarlos de manera annima, es decir, sin necesidad de saber si estamos usando un objeto de una clase o de otra, ya que si ambas clases implementan la interfaz, tendremos la certeza de que dichas clases tienen los miembros definidos en dicha interfaz. Una interfaz representa un contrato, si una clase implementa una interfaz, est suscribiendo dicho contrato, es ms, est obligada a cumplirlo, por tanto, la clase tendr que definir todos los miembros que la interfaz contenga. Antes de ver cmo usar las interfaces en nuestras clases, veamos cmo definir una interfaz.
Public Interface IPrueba2 Property Prop1() As String Sub Mostrar() End Interface

En este caso hemos definido una interfaz llamada IPrueba2 (por convencin los nombres de las interfaces siempre empiezan con la letra I mayscula), en la que se define una propiedad y un mtodo. Los miembros de las interfaces siempre son pblicos y no deben implementar cdigo, solamente la definicin propiamente dicha.

UTILIZAR INTERFACES EN LAS CLASES


Cualquier clase que quiera disponer de los miembros definidos en la interfaz debe indicarlo de forma expresa, ya que no solo es suficiente con definir los miembros con nombres y caractersticas similares. Para "implementar" en una clase los miembros definidos en una interfaz tendremos que usar la instruccin Implements seguida del nombre de la interfaz. Adems tendremos que definir los mtodos y propiedades que dicha interfaz contiene, aunque en Visual Basic adems hay que indicarlo expresamente, de forma que se sepa con seguridad de que cada uno de esos miembros equivale a los definidos en la interfaz. En el listado 4 vemos cmo definir una clase que utilice la interfaz que acabamos de ver en la seccin anterior.

Public Class Prueba2 Implements IPrueba2

Public Sub Mostrar() _ Implements IPrueba2.Mostrar ' nuestra version del mtodo Mostrar End Sub

Public Property Prop1() As String _ Implements IPrueba2.Prop1 Get ' el cdigo que devuelve ' el valor de la propiedad End Get Set(ByVal value As String) ' el cdigo que asigna ' el valor de la propiedad End Set End Property End Class

Listado 4 El mtodo y las dos propiedades deben tener el mismo nombre y parmetros (si los hubiera) que los definidos en la interfaz. Cuando trabajamos con Visual Basic adems debemos indicar expresamente que dicho mtodo o propiedad est "ligado" con el definido en la interfaz, cuando trabajamos con C# no es necesario indicarlo. La ventaja de esta "redundancia" de VB es que podemos dar un nombre diferente al miembro implementado, pero "internamente" el compilador sabr que nos estamos refiriendo al que implementa la interfaz. Tal como podemos ver en el listado 5, a pesar de que en la clase Prueba2B al mtodo le hemos dado otro nombre, realmente est haciendo referencia al que se ha declarado en la interfaz.
Public Class Prueba2B Implements IPrueba2

Public Sub OtroNombre() _ Implements IPrueba2.Mostrar Console.WriteLine("Este es el mtodo Mostrar de la clase Prueba2B") End Sub

Public Property Prop1() As String _ Implements IPrueba2.Prop1 Get Return "Prop1 de la clase prueba2B" End Get Set(ByVal value As String) ' End Set End Property End Class

Dim p2 As New Prueba2 Dim p2b As New Prueba2B Dim i As IPrueba2 ' i = p2 i.Mostrar() ' i = p2b i.Mostrar()

Listado 5

POLIMORFISMO USANDO CLASES E INTERFACES


En los ejemplos mostrados ya hemos visto cmo usar el polimorfismo tanto a travs de variables incluidas en las clases como con interfaces que dichas clases implementan; vamos a detallar un poco ms, ya que esta es una de las caractersticas ms usadas en .NET, por la sencilla razn de que muchas clases de .NET Framework implementan interfaces de forma que podamos acceder a los miembros implementados por medio de variables del tipo de dichas interfaces. Es ms, muchas de las clases de .NET adems permiten que demos nueva funcionalidad a nuestras propias clases si implementamos ciertas interfaces. Por ejemplo, si queremos que nuestra clase sea "clasificable", es decir, que se pueda usar en una coleccin que clasifique los elementos que contiene, nuestra clase debe implementar la interfaz IComparable. Si definimos una clase en la que queremos que el mtodo ToString acte de forma que podamos especificar ciertos formatos a la hora de mostrar el contenido, nuestra clase debe implementar IFormattable. Que queremos que nuestra clase acte como una coleccin, en la que se pueda enumerar o recorrer el contenido de la misma, debemos implementar la interfaz IEnumerable. Pero esas interfaces propias del .NET Framework lo que harn ser darle una nueva funcionalidad a nuestras clases, por tanto, lo importante es saber de que forma actan los objetos creados en la memoria. Tal como hemos comentado antes, solo existe un objeto en la memoria y cuando accedemos a l lo podemos hacer bien usando alguna de las clases de las que se deriva o bien mediante alguna de las interfaces que

implementa. Cuando accedemos a dicho objeto mediante algunas de estas clases o interfaces simplemente estamos accediendo a la parte "conocida" por dicho tipo. En el cdigo del listado 4 y 5 la interfaz IPrueba2 "sabe" cmo acceder al mtodo Mostrar y a la propiedad Prop1, independientemente del objeto que la haya implementado, por tanto si una clase implementa dicha interfaz podemos acceder a esos miembros mediante una variable del tipo IPrueba2, tal como se demuestra en el listado 5 en el que accedemos al mtodo Mostrar definido en la interfaz e implementado por las dos clases.

USAR EL POLIMORFISMO PARA ACCEDER A ELEMENTOS DIFERENTES DE UN ARRAY O COLECCIN


Una de las utilidades del polimorfismo (de clases o interfaces) es que podemos crear arrays de variables de un tipo "bsico" y en ese array incluir objetos que si bien son distintos, en el fondo tienen como parte componente la clase de la que se ha declarado el array. El ejemplo ms bsico y vlido tanto para las clases declaradas en el propio .NET Framework como las declaradas por nosotros mismos, es crear un array de tipo Object, dicho array podr contener objetos de cualquier tipo (incluso tipos como nmeros enteros, cadenas, etc.), y posteriormente poder acceder a cualquiera de los elementos mediante un objeto del tipo Object, en cuyo caso solo podremos acceder a los mtodos que Object implementa o bien mediante objetos de un tipo en particular, en cuyo caso nos veremos obligados a hacer una conversin desde el tipo contenido en el array (Object) al tipo particular que nos interese. En el listado 6 podemos ver un ejemplo en el que se crea un array de tipo Object pero que se almacenan tanto objetos del tipo clase A, clase B, IPrueba2, Integer y String.
Dim a(6) As Object ' Dim a1 As New A a1.Prop1 = "Objeto A" Dim b1 As New B b1.Prop1 = "Objeto B" Dim c1 As New C c1.Prop1 = "Objeto C" ' a(0) = a1 a(1) = b1 a(2) = c1 a(3) = New Prueba2 a(4) = New Prueba2B a(5) = 15 a(6) = "Hola" ' Dim i As Integer Console.Write("Usando el mtodo ToString")

Console.WriteLine(" de los objetos contenidos") For i = 0 To a.Length - 1 Console.WriteLine("a({0}) = {1}", i, a(i).ToString()) Next ' Console.WriteLine() ' Console.WriteLine("Usando un Object") Dim o As Object For Each o In a Console.WriteLine("o.ToString = {0}", o.ToString()) Next ' Console.WriteLine() ' Console.WriteLine("Usando tipos especficos") For Each o In a Console.WriteLine("El tipo es: {0}", o.GetType().Name) If TypeOf o Is A Then Dim tA As A = CType(o, A) tA.Mostrar() ElseIf TypeOf o Is IPrueba2 Then Dim tIPrueba2 As IPrueba2 = CType(o, IPrueba2) tIPrueba2.Mostrar() ElseIf TypeOf o Is Integer Then Dim tInt As Integer = CType(o, Integer) Console.WriteLine(tInt.ToString("00000")) ElseIf TypeOf o Is String Then Dim tStr As String = o.ToString Console.WriteLine(tStr) Else Console.WriteLine("o.ToString = {0}", o.ToString()) End If Next

Listado 6 Tal como podemos comprobar en el ltimo bucle de dicho listado, se utiliza la instruccin compuesta TypeOf ... Is para saber si un objeto es de un tipo concreto (en C# usaramos is), tambin podemos ver que usando el mtodo GetType podemos obtener el tipo subyacente as como el nombre de dicho tipo.

Si nos fijamos, al hacer la comprobacin TypeOf o Is A aqu se procesarn tanto los objetos del tipo A como los derivados de dicho tipo, lo mismo ocurre con la interfaz IPrueba2. Pero este ejemplo al ser genrico y usando la clase Object seguramente no acabar de "cuajar", por tanto vamos a crear un ejemplo en el que crearemos variables de un tipo concreto: Cliente y derivaremos un par de clases en las que agregaremos nueva funcionalidad a la clase base, posteriormente crearemos un array del tipo Cliente en el que podremos almacenar variables de cualquiera de esos tipos derivados de ella.

Nota: Por la extensin del listado, el mismo se incluye en el ZIP con el cdigo de los ejemplos (tanto para Visual Basic como para C#), en el listado 7 puedes ver cmo usar esas clases.

En dicho cdigo tendremos ocasin de ver cmo podemos implementar la interfaz IComparable para que estas clases se puedan agregar a una coleccin y posteriormente clasificarlas. Adems implementaremos la interfaz IFormattable para que, si los mostramos por la consola o usamos el mtodo Format de la clase String, podamos usar los siguientes formatos personalizados: ANS mostrar los apellidos, el nombre y el saldo NAS mostrar el nombre, los apellidos y el saldo AN mostrar los apellidos y el nombre (predeterminado) NA mostrar el nombre y los apellidos S mostrar el saldo

Sub Main() Dim acli(6) As Cliente ' acli(0) = New Cliente("Jose", "Sanchez", 125.5D) acli(1) = New ClienteOro("Luis", "Rebelde", 2500.75D) acli(2) = New ClienteMoroso("Antonio", "Perez", -500.25D) acli(3) = New Cliente("Miguel", "Rodriguez", 200) acli(4) = New ClienteMoroso("Juan", "Ruiz", -310) acli(5) = New ClienteOro("Mariano", "Alvarez", 500.33D) acli(6) = New Cliente("Carlos", "Bueno", 975) ' Console.WriteLine("Antes de clasificar:") For Each c As Cliente In acli Console.WriteLine("{0}, saldo= {1}", c, c.MostrarSaldo()) Next Array.Sort(acli)

' Console.WriteLine() Console.WriteLine("Despus de clasificar:") For Each c As Cliente In acli Console.Write("{0}, saldo= {1}", c, c.MostrarSaldo()) If TypeOf c Is ClienteOro Then Console.WriteLine(" -> $$$ es cliente ORO $$$") ElseIf TypeOf c Is ClienteMoroso Then Console.WriteLine(" -> OJO que es un cliente moroso") Else Console.WriteLine() End If Next ' Console.WriteLine() Console.WriteLine("Mostrar usando formatos:") For Each c As Cliente In acli Console.WriteLine("Usando NAS= {0:NAS}", c) Console.WriteLine("Usando AN= {0:AN}", c) Console.WriteLine("Usando S= {0:S}", c) Next ' Console.ReadLine() End Sub

Listado 7

CONSTRUCTORES Y SOBRECARGA DE CONSTRUCTORES


El punto de inicio de cualquier clase, cuando se crea una instancia en la memoria, es un mtodo especial al que se le conoce como constructor. Un constructor no devuelve ningn valor, por tanto en Visual Basic sera un mtodo de tipo Sub llamado New (en C# no se declara como void, simplemente tendr el mismo nombre de la clase). Los constructores tambin se pueden sobrecargar, es decir, pueden existir varias versiones en las que cada una de ellas reciba distintos parmetros, en nmero y/o en tipo. Debido a que todas las clases (y estructuras) deben tener un constructor, si nosotros no lo definimos de forma expresa, ser el propio compilador el que se encargue de aadirlo por nosotros, en ese caso ser un constructor en el que no se reciba ningn argumento. Aunque hay que tener presente que en el momento en que hemos definido un constructor el compilador ya no agregar ninguno de forma automtica. Esto tiene sus ventajas, ya que en ocasiones es posible que nos

interese que nuestras clases solamente se puedan instanciar si se le pasa algunos parmetros al constructor de la misma. Pero si adems de un constructor con parmetros queremos seguir manteniendo el constructor "predeterminado", entonces tendremos que declararlo aunque no escribamos nada de cdigo en el interior. En el listado 8 podemos ver la clase Cliente con tres constructores.
Public Class Cliente Implements IComparable, IFormattable ' Private _nombre As String Private _apellidos As String Private _saldo As Decimal ' Public Sub New() End Sub

Public Sub New( _ ByVal elNombre As String, _ ByVal losApellidos As String) _nombre = elNombre _apellidos = losApellidos End Sub

Public Sub New( _ ByVal elNombre As String, _ ByVal losApellidos As String, _ ByVal elSaldo As Decimal) _nombre = elNombre _apellidos = losApellidos _saldo = elSaldo End Sub

Listado 8

LOS CONSTRUCTORES NO SE HEREDAN El constructor es el nico miembro de una clase que no se hereda, por tanto si necesitamos crear constructores en clases derivadas debemos declararlos de forma explcita.

LOS CONSTRUCTORES DE LAS ESTRUCTURAS


Los constructores de las estructuras son un caso especial, ya que siempre existir un constructor sin parmetros, el cual adems no podemos definirlo por medio de cdigo, porque es el propio compilador el que se encargar de su creacin. Por tanto en las estructuras solamente podemos definir constructores parametrizados (que reciban parmetros) y en el caso de definirlo, en el cdigo del mismo, tendremos que asignarle un valor a cualquiera de las propiedades (o campos) pblicos que tenga esa estructura, siempre y cuando no sean estticos (compartidos).

CONSTRUCTORES QUE USAN OTROS CONSTRUCTORES


Debido a que los constructores pueden recibir parmetros, en algunas ocasiones nos puede ser til poder llamar a otros constructores, por ejemplo de la clase base o de la misma clase. En estos casos, en Visual Basic es fcil hacerlo, como sabemos que los constructores realmente son mtodos llamados New, los podemos usar de la misma forma que haramos con cualquier otro mtodo. Por ejemplo, si modificamos el cdigo mostrado en el listado 8, podramos hacer esto:
Public Sub New( _ ByVal elNombre As String, _ ByVal losApellidos As String, _ ByVal elSaldo As Decimal)

Me.New(elNombre, losApellidos) _saldo = elSaldo

End Sub

De forma que desde el constructor que recibe tres parmetros llamemos al que recibe dos. En este caso, la instruccin o palabra clave Me representa a la instancia actual (el objeto que se ha creado en memoria). Si en lugar de llamar a otro constructor de la propia clase, queremos llamar a un constructor de la clase base, en lugar de Me, usaremos MyBase. En C# este mismo cdigo se hara de la siguiente forma:
public Cliente(string elNombre, string losApellidos, decimal elSaldo) : this(elNombre, losApellidos) { _saldo = elSaldo;

Es decir, se llamara al otro constructor indicndolo despus del cierre de parntesis y separndolo con dos puntos. En C# la instruccin o palabra clave que hace referencia a la instancia actual es this y la que hace referencia a la clase base es: base.

CLASES ABSTRACTAS
Tal como comentamos el mes anterior, en ocasiones tendremos la necesidad de crear clases que no se puedan usar para crear objetos, pero si para usarla como base de otras. La razn principal para que hacer que una clase no sea instanciable es que dicha clase por s sola no tenga ningn sentido, al menos para poder crear nuevos objetos de ese tipo, pero si tendr sentido si la usamos como clase base de otras clases. Por ejemplo, podramos tener una clase Animal, la cual no tendra sentido si a partir de ella se pudiesen crear nuevos objetos, ya que el concepto de animal es demasiado abstracto para poder crear un objeto a partir de l. Pero si la podramos utilizar para derivar de ella otras clases que bien podran ser a la vez abstractas o bien clases "normales". .NET Framework nos permite crear clases abstractas, las cuales son como las interfaces, pero las que pueden tener mtodos y otros miembros que tengan no solo la definicin de esos miembros sino tambin cdigo funcional. Adems, debido a que las clases abstractas estn pensadas para usarse como clases base de otras, todos los miembros son virtuales de forma predeterminada, por tanto no es necesario indicarlos usando el modificador Overridable (virtual en C#).

DECLARAR CLASES ABSTRACTAS


La definicin de una clase abstracta se hace como las clases normales, salvo de que hay que usar el modificador MustInherit (abstract en C#), de esta forma le indicamos al compilador de que nuestra intencin es la de que nuestra clase sea "heredable". Como ya hemos comentado anteriormente, el concepto de clases abstractas o clases que solo se pueden usar como clases base es importante cuando queremos ofrecer cierta funcionalidad a nuestras clases, sobre todo las que formen parte de ciertas jerarquas de clases, ya que las clases abstractas nos servirn para definir el comportamiento del resto de las clases, adems de que, como las interfaces, nos permitirn disponer de cierta funcionalidad o, mejor dicho, nos permitirn dar unas pautas que los que decidan usarlas, tendrn que seguir. Pero a diferencia de las interfaces, las clases abstractas no solo representarn un contrato, sino que tambin pueden ofrecer "de fbrica" un funcionamiento que, aunque las clases derivadas no implementen, stas ya tendrn, en este aspecto funcionarn como las clases normales, ya que las clases derivadas podrn usar el cdigo implementado en ellas.

MIEMBROS ABSTRACTOS
Cuando comentamos que las clases abstractas son como las interfaces no solo nos referamos a que se podran usar para proporcionar polimorfismo, sino porque en las clases abstractas tambin podemos definir miembros que a su vez sean abstractos, es decir, que en las clases abstractas solamente se defina el mtodo o propiedad, pero que no tenga ninguna funcionalidad, es ms, si declaramos un miembro como abstracto la clase que se derive de la clase abstracta estar obligada a definirlo.

Esto nos ofrece la ventaja de poder definir miembros funcionales y miembros que solo tengan sentido en las clases derivadas y por tanto sern las clases derivadas las que deban definir el cdigo que los haga funcionales y le den la utilidad adecuada. Para indicar que un miembro es abstracto, debemos indicarlo usando la instruccin MustOverride (abstract en C#), de esta forma nos permitir el compilador escribir solo la definicin del mismo y no tener que escribir ningn cdigo. En las clases derivadas tendremos que usar la instruccin Overrides (override en C#) de la misma forma que lo usamos con el resto de las clases para indicar que dicho mtodo est reemplazando a un miembro definido en la clase base. Una puntualizacin: Los miembros abstractos solo se pueden definir en clases abstractas. En el cdigo incluido en el ZIP que acompaa a este artculo se incluye un ejemplo que define y usa las clases abstractas, como es habitual, se incluye cdigo para Visual Basic y C#.

CLASES SELLADAS (NO HEREDABLES)


Otro concepto, que posiblemente pueda parecer que no est "ligado" con la herencia es el de las clases selladas o no heredables. Este tipo de clases no permitirn que se usen como clases base de otras nuevas clases. La existencia de las clases normales y las abstractas nos permiten derivar nuevas clases a partir de ellas, eso tiene sentido, pero, qu sentido puede tener una clase de la que no se puedan derivar nuevas clases? La razn principal para definir una clase como sellada o no heredable es precisamente porque no queremos que nadie pueda modificar el comportamiento de dicha clase, ya que al no poder usarla como base de nuevas clases, nadie podr ofrecer nueva funcionalidad, de esta forma nos aseguramos que esa clase siempre funcionar como la hemos definido. Esto es as, porque al estar "sellada" tampoco podremos definir miembros virtuales, por la sencilla razn de que nadie podr derivar nuevas clases y por tanto tampoco podr reemplazar el comportamiento de los mismos. Debido a que el comportamiento normal de una clase es que sea heredable, para poder crear clases que estn selladas, y por tanto hacerlas no heredables, debemos usar la instruccin o modificador NotInheritable (sealed en C#).

Conclusiones
Confo que todo el tema tratado sobre la programacin orientada a objetos, y por extensin a la herencia, desde el punto de vista de un programador de .NET Framework nos permita afrontar todo este tema, que si bien al principio puede parecer algo "escabroso", realmente debera ser una forma natural de programar, sobre todo si tenemos en cuenta que todo el .NET Framework se basa en las clases, interfaces y dems conceptos relacionados con la POO.

Introduccin a los objetos en Visual Basic


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Un objeto es una estructura que contiene la informacin y los mtodos que manipulan los datos. Casi todas las tareas realizadas en Visual Basic estn asociadas con objetos. Si no tiene experiencia en programacin orientada a objetos, los siguientes trminos y conceptos le ayudarn a comenzar.

Clases y objetos

Las palabras "clase" y "objeto" se usan con tanta frecuencia en la programacin orientada a objetos que es fcil confundir los trminos. En general, una class es una representacin abstracta de algo, mientras que un objeto es un ejemplo utilizable de lo que representa la clase. La nica excepcin a esta regla la constituyen los miembros de clases compartidas, que pueden utilizarse en instancias de una clase y en variables de objeto declaradas como tipo de la clase.

Campos, propiedades, mtodos y eventos

Las clases se componen de campos, propiedades, mtodos y eventos. Los campos y propiedades representan informacin que contiene un objeto. Los campos se parecen a las variables ya que se pueden leer y establecer directamente. Por ejemplo, si tiene un objeto denominado "Car", podra almacenar su color en un campo denominado "Color". Las propiedades se recuperan y establecen como los campos, pero se implementan mediante los procedimientos propiedad Get y Set, que proporcionan ms control sobre la forma en que los valores se establecen o se devuelven. El nivel de direccionamiento indirecto entre el valor que se va a almacenar y los procedimientos que lo usan ayuda a aislar los datos y permite validar valores antes de asignarlos o recuperarlos. Los mtodos representan acciones que un objeto puede realizar. Por ejemplo, un objeto "Car" podra tener los mtodos "StartEngine", "Drive" y "Stop". Los mtodos se definen agregando procedimientos, ya sean rutinas o funciones Sub, a la clase. Los eventos son notificaciones que un objeto recibe de, o transmite a, otros objetos o aplicaciones. Los eventos permiten a los objetos realizar acciones siempre que se produce un acontecimiento especfico. Un ejemplo de evento para la clase "Car" sera un evento "Check_Engine". Puesto que Microsoft Windows es un sistema controlado por eventos, stos pueden proceder de otros objetos, aplicaciones o entradas de usuario realizadas al hacer clic con el mouse (ratn) o al presionar teclas.

Encapsulacin, herencia y polimorfismo

Los campos, propiedades, mtodos y eventos son solamente la mitad de la ecuacin de la programacin orientada a objetos. Para que la programacin orientada a objetos sea autntica los objetos deben admitir tres cualidades: encapsulacin, herencia y polimorfismo. La encapsulacin significa que un grupo de propiedades, mtodos y otros miembros relacionados se tratan como si de una sola unidad u objeto se tratase. Los objetos pueden controlar cmo se cambian propiedades o se ejecutan mtodos. Por ejemplo, un objeto puede validar valores antes de permitir cambios en la propiedad. La encapsulacin, adems, facilita la posibilidad de realizar cambios en la implementacin pasado algn tiempo, mediante una actividad denominada ocultacin de datos que permite ocultar los detalles de implementacin de los objetos. Herencia describe la posibilidad de crear nuevas clases basadas en una clase existente. La nueva clase hereda todas las propiedades, mtodos y eventos de la clase base, y puede personalizarse con propiedades y mtodos adicionales. Por ejemplo, puede crear una nueva clase denominada "Truck" basada en la clase "Car". La clase "Truck" hereda la propiedad "Color" de la clase "Car" y puede tener propiedades adicionales como "FourWheelDrive". Polimorfismo significa que puede tener mltiples clases que se pueden utilizar de forma intercambiable, si bien cada clase implementa las mismas propiedades o los mismos mtodos de maneras diferentes. El polimorfismo es importante en la programacin orientada a objetos puesto que permite usar elementos que tienen el mismo nombre, independientemente del tipo de objeto que se est utilizando en ese momento. Por ejemplo, dada una clase base "Car", el polimorfismo permite al programador definir diferentes mtodos "StartEngine" para cualquier nmero de clases derivadas. El mtodo "StartEngine" de una clase derivada denominada "DieselCar" puede ser totalmente diferente del mtodo con el mismo nombre en la clase base. Otros procedimientos o mtodos pueden usar el mtodo "StartEngine" de las clases derivadas de la misma forma, con independencia del tipo de objeto "Car" que se est utilizando en ese momento.

Sobrecarga, reemplazo y sombreado

La sobrecarga, el reemplazo y el sombreado son conceptos similares que pueden confundirse fcilmente. Aunque las tres tcnicas permiten crear miembros con el mismo nombre, existen algunas diferencias importantes.

Los miembros sobrecargados se utilizan para proporcionar diferentes versiones de una propiedad o mtodo que tienen el mismo nombre, pero que aceptan un nmero diferente de parmetros, o parmetros con diferentes tipos de datos. Las propiedades y mtodos reemplazados se utilizan para reemplazar una propiedad o mtodo heredados que no son apropiados en una clase derivada. Los miembros reemplazados deben aceptar el mismo tipo de datos y nmero de argumentos. Las clases derivadas heredan los miembros reemplazados. Los miembros sombreados se utilizan para reemplazar localmente un miembro que tiene un mbito ms amplio. Cualquier tipo puede sombrear cualquier otro tipo. Por ejemplo, puede

declarar un propiedad que sombree un mtodo heredado con el mismo nombre. Los miembros sombreados no se pueden heredar.

Clases: como planos para objetos


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Las clases son representaciones simblicas de objetos; describen las propiedades, campos, mtodos y eventos que forman objetos de la misma forma que los planos describen los elementos que componen un edificio. As como un plano puede utilizarse para crear varios edificios, una nica clase puede utilizarse para crear tantos objetos como sea necesario. Del mismo modo que un plano define qu partes de un edificio son accesibles a las personas que lo utilizan, las clases tambin pueden controlar el acceso de los usuarios a los elementos de objetos a travs de la encapsulacin.

Clases y objetos

Los trminos clase y objeto se utilizan a veces indistintamente, pero en realidad, las clases describen la estructura de los objetos, mientras que los objetos son instancias de clases que se pueden utilizar. Cada instancia es una copia exacta pero diferente de su clase. Puesto que un objeto es una instancia de una clase, la accin de crear un objeto se denomina creacin de instancias. Con la analoga de plano, una clase es un plano y un objeto es un edificio construido a partir de ese plano. Normalmente, al cambiar los datos en un objeto, no se cambian los datos en ningn otro objeto. (La excepcin la constituyen los miembros compartidos, miembros de clase declarados con el modificador Shared, que existen de forma independiente de las instancias especficas de una clase).

Encapsulacin

La encapsulacin es la capacidad de contener y controlar el acceso a un grupo de elementos asociados. Las clases proporcionan una de las formas ms comunes de encapsular elementos. En el ejemplo siguiente, la clase BankAccount encapsula los mtodos, campos y propiedades que describen una cuenta bancaria.

Sin la encapsulacin, debera declarar diferentes procedimientos y variables para almacenar y administrar la informacin de la cuenta bancaria, y sera difcil trabajar con ms de una cuenta bancaria a la vez. La encapsulacin permite utilizar datos y procedimientos de la clase BankAccount como una unidad. Puede trabajar con varias cuentas bancarias al mismo tiempo sin confusin, puesto que cada cuenta se representa mediante una instancia nica de la clase. La encapsulacin tambin permite controlar la forma de utilizar los datos y los procedimientos. Se pueden utilizar modificadores de acceso, como Private o Protected, para evitar que unos procedimientos externos ejecuten mtodos de clase o lean y modifiquen datos en propiedades y campos. Debe declarar detalles internos de una clase como Private para evitar que se utilicen fuera de su clase; esta tcnica se llama ocultacin de datos y es el modo de proteger informacin del cliente, como un saldo de cuenta por ejemplo. Una regla bsica de la encapsulacin es que los datos de clase slo se deben modificar o recuperar mediante mtodos o procedimientos Property. Al ocultar los detalles de implementacin de las clases se evita que sean utilizados de forma no deseada y hace posible la modificacin posterior de tales elementos sin problemas de compatibilidad. Por ejemplo, en las versiones posteriores de la clase BankAccount se podra cambiar el tipo de datos del campo AccountBalance sin peligro de interrumpir otras aplicaciones que se basan en que ese campo tenga un tipo de datos especfico.

Herencia

Al igual que para las estructuras de Visual Basic, puede utilizar las clases para definir tipos de datos que encapsulan un grupo de elementos relacionados. No obstante, a diferencia de las estructuras, las clases de Visual Basic pueden heredar y extender las caractersticas de otras clases. Las clases que sirven de base para nuevas clases se denominan clases base. Las clases que se derivan de clases base se denominan clases derivadas. Las clases derivadas heredan todos los campos, propiedades, mtodos y eventos de la clase base. Esto significa que puede desarrollar y depurar una clase una vez y reutilizarla despus como base de otras clases. En el siguiente ejemplo se define una clase base que representa una cuenta bancaria genrica y una clase especfica que hereda las propiedades de la clase base pero que se personaliza para describir una cuenta corriente.

VB C# C++ F#

JScript

Copiar Class BankAccount Private AccountNumber As String Private AccountBalance As Decimal Private HoldOnAccount As Boolean = False Public Sub PostInterest() ' Add code to calculate the interest for this account. End Sub ReadOnly Property Balance() As Decimal Get ' Return the available balance. Return AccountBalance End Get End Property End Class

Class CheckingAccount Inherits BankAccount Sub ProcessCheck() ' Add code to process a check drawn on this account. End Sub End Class

Para obtener ms informacin sobre herencias, consulte Fundamentos de la herencia.

Miembros compartidos

De forma predeterminada, los datos de clase se especifican para cada instancia de la clase, pero en ocasiones puede ser deseable compartir un solo elemento de datos entre todos los objetos creados a partir de una clase. En casos como ste, utilice el modificador Shared para hacer que una variable comparta el mismo valor en todas las instancias de una clase (los miembros Shared a veces se llaman "miembros estticos" en otros lenguajes de programacin). Los mtodos compartidos pueden llamarse directamente mediante un nombre de clase sin necesidad de crear previamente una instancia de la clase. Para obtener ms informacin acerca de miembros compartidos, consulte Miembros compartidos en Visual Basic.

Sombrear

Las clases derivadas pueden utilizar la palabra clave Shadows para declarar un miembro con el mismo nombre que un miembro heredado. El tipo de datos de los miembros sombreados no es necesario que sea el mismo que el del miembro que se sombrea. Por ejemplo, una propiedad puede sombrear una variable de tipo Integer. Para obtener ms informacin acerca de miembros compartidos, consulte Sombrear en Visual Basic.

Tutorial: Definir clases (Visual Basic)


Visual Studio 2010 Otras versiones

Este tutorial muestra cmo definir clases que se pueden utilizar luego para crear objetos.Tambin muestra cmo agregar propiedades y mtodos a las clases nuevas, e indica cmo inicializar un objeto.

Nota
Es posible que su equipo muestre nombres o ubicaciones diferentes para algunos de los elementos de la interfaz de usuario de Visual Studio incluidos en las instrucciones siguientes. La edicin de Visual Studio que se tenga y la configuracin que se utilice determinan estos elementos. Para obtener ms informacin, vea Valores de configuracin de Visual Studio.

Para definir una clase


1. 2. 3. 4. 5. Cree un proyecto haciendo clic en Nuevo proyecto en el men Archivo.Aparecer el cuadro de dilogo Nuevo proyecto. Seleccione Aplicacin para Windows de la lista de plantillas del proyecto de Visual Basic para mostrar el nuevo proyecto. Agregue una clase nueva al proyecto haciendo clic en Agregar clase en el men Proyecto.Aparecer el cuadro de dilogo Agregar nuevo elemento. Seleccione la plantilla Clase. Asigne a la nueva clase el nombre UserNameInfo.vb y, a continuacin, haga clic en Agregar para mostrar el cdigo de la nueva clase.

VB C# C++ F# JScript

Copiar

Public Class UserNameInfo End Class

Nota
Puede utilizar el Editor de cdigo de Visual Basic para agregar una clase al formulario de inicio escribiendo la palabra clave Class seguida del nombre de la clase nueva.El Editor de cdigo proporciona la instruccin End Class correspondiente.

6.

Defina un campo privado para la clase; para ello, agregue el siguiente cdigo entre las instrucciones Class y End Class:

VB C# C++ F# JScript

Copiar

Private userNameValue As String

Declarar el campo como Private quiere decir que slo se puede utilizar dentro de la clase.Se pueden utilizar modificadores de acceso ms amplio, por ejemplo Public, para hacer que los campos estn disponibles desde fuera de la clase.Para obtener ms informacin, vea Niveles de acceso en Visual Basic. 7. Defina una propiedad para la clase agregando el cdigo siguiente:

VB C# C++ F# JScript

Copiar

Public Property UserName() As String Get ' Gets the property value. Return userNameValue End Get

Set(ByVal Value As String) ' Sets the property value. userNameValue = Value End Set End Property

8.

Defina un mtodo para la clase agregando el cdigo siguiente:

VB C# C++ F# JScript

Copiar

Public Sub Capitalize() ' Capitalize the value of the property. userNameValue = UCase(userNameValue) End Sub

9.

Defina un constructor parametrizado para la clase nueva agregando un procedimiento denominado Sub New:

VB C# C++ F# JScript

Copiar

Public Sub New(ByVal UserName As String) ' Set the property value. Me.UserName = UserName End Sub

Cuando se crea un objeto basado en esta clase, se llama al constructor Sub New automticamente.Este constructor establece el valor del campo que contiene el nombre de usuario.

Para crear un botn que pruebe la clase


1. Cambie el formulario de inicio al modo de diseo haciendo clic con el botn secundario del mouse en su nombre desde el Explorador de soluciones y, a continuacin, haga clic en Diseador de vistas.De forma predeterminada, el nombre que se asigna al formulario de inicio para los proyectos de aplicacin para Windows es Form1.vb.Aparecer el formulario principal. Agregue un botn al formulario principal y haga doble clic en l para mostrar el cdigo del controlador de eventos Button1_Click.Agregue el cdigo siguiente para llamar al procedimiento de prueba:

2.

VB C# C++ F# JScript

Copiar

' Create an instance of the class. Dim user As New UserNameInfo("Moore, Bobby") ' Capitalize the value of the property. user.Capitalize() ' Display the value of the property. MsgBox("The original UserName is: " & user.UserName)

' Change the value of the property. user.UserName = "Worden, Joe" ' Redisplay the value of the property. MsgBox("The new UserName is: " & user.UserName)

Para ejecutar la aplicacin


1. Presione F5para ejecutar la aplicacin.Llame al procedimiento de prueba haciendo clic en el botn del formulario.Muestra un mensaje que indica que el UserName original es "MOORE, BOBBY", porque el procedimiento llam al mtodo Capitalize del objeto. Haga clic en Aceptar para descartar el cuadro de mensaje.El procedimiento Button1 Click cambia el valor de la propiedad UserName y muestra un mensaje que indica que el nuevo valor de UserName es "Worden, Joe."

2.

Clases y mdulos
Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Tanto las clases como los mdulos son tipos de referencia que encapsulan los elementos definidos en ellos, pero difieren en la forma en que se realiza el acceso a los elementos desde otros procedimientos.

Diferencias entre clases y mdulos

La diferencia principal entre clases y mdulos consiste en que pueden crearse instancias de clases como objetos pero no de mdulos. Como slo existe una copia de los datos de un mdulo estndar, cuando una parte del programa cambia una variable pblica en un mdulo estndar, cualquier otra parte del programa obtendr el mismo valor si lee luego esa variable. En comparacin, los datos de objeto existen individualmente para cada objeto con instancias. Otra distincin es que, a diferencia de los mdulos estndar, las clases pueden implementar interfaces.

Nota:
Cuando el modificador Shared se aplica a un miembro de clase, est asociado con la propia clase en lugar de con una instancia determinada de la clase. Se tiene acceso directo al miembro mediante el nombre de clase, de la misma manera que se tiene acceso a los miembros de mdulos. Para obtener ms informacin acerca de miembros compartidos, consulte Miembros compartidos en Visual Basic.

Las clases y los mdulos tambin emplean mbitos diferentes para sus miembros. Los miembros definidos dentro de una clase tienen el mbito de una instancia especfica de la clase y slo existen mientras dure el objeto. Para tener acceso a los miembros de clases desde el exterior de una clase, debe utilizar los nombres completos con el formato Objeto.Miembro. Por otro lado, los miembros declarados dentro de un mdulo son de manera predeterminada accesibles pblicamente y se puede obtener acceso a ellos mediante cualquier cdigo que tenga acceso al mdulo. Esto significa que las variables en un mdulo estndar son de hecho variables globales porque son visibles desde cualquier parte del proyecto y existen durante toda la vida til del programa.

Duracin de los objetos: cmo se crean y destruyen (Visual Basic)


Visual Studio 2010 Otras versiones

Una instancia de una clase (un objeto) se crea mediante la palabra clave New.A menudo hay que realizar tareas de inicializacin en los objetos nuevos antes de utilizarlos.Entre las tareas de inicializacin comunes se incluyen abrir archivos, conectar con bases de datos y leer valores de claves del Registro.Visual Basic controla la inicializacin de objetos nuevos mediante unos procedimientos denominados constructores (mtodos especiales que proporcionan control sobre la inicializacin). Common Language Runtime (CLR) libera un objeto cuando ste ha salido del mbito.Visual Basic controla la liberacin de recursos del sistema mediante unos procedimientos denominados destructores.Juntos, los constructores y destructores permiten la creacin de bibliotecas de clases robustas y predecibles.

Utilizar constructores y destructores

Los constructores y destructores controlan la creacin y destruccin de objetos.Los procedimientos Sub New y Sub Finalize de Visual Basic inicializan y destruyen objetos; reemplazan a los mtodos Class_Initialize y Class_Terminate que se utilizaban en Visual Basic 6.0 y versiones anteriores.

Sub New
El constructor Sub New slo puede ejecutarse una vez cuando se crea una clase.Slo se le puede llamar explcitamente desde la primera lnea de cdigo de otro constructor en la misma clase o en una clase derivada.Adems, el cdigo del mtodo Sub New siempre se ejecuta antes de cualquier otro cdigo en una clase.Visual Basic 2005 y las versiones posteriores crean implcitamente en tiempo de ejecucin un constructor Sub New si no define explcitamente un procedimiento Sub New para una clase. Para crear un constructor para una clase, cree un procedimiento denominado Sub New en cualquier parte de la definicin de clase.Para crear un constructor parametrizado, especifique los nombres y los tipos de datos de los argumentos de Sub New tal como lo hara en cualquier otro procedimiento, como en el cdigo siguiente:

VB C# C++ F# JScript

Copiar

Sub New(ByVal s As String)

Con frecuencia, los constructores estn sobrecargados, como en el cdigo siguiente:

VB C# C++ F# JScript

Copiar

Sub New(ByVal s As String, i As Integer)

Cuando se define una clase derivada de otra, la primera lnea del constructor debe ser una llamada al constructor de la clase base, a no ser que sta tenga un constructor accesible que no requiera parmetros.Por ejemplo, para llamar a la clase base que contiene el constructor anterior, sera MyBase.New(s).En caso contrario, MyBase.New es opcional y el tiempo de ejecucin de Visual Basic la llama implcitamente. Despus de escribir cdigo para llamar al constructor del objeto primario, se puede agregar cdigo de inicializacin al procedimiento Sub New.Sub New puede aceptar argumentos cuando se llama como constructor parametrizado.Estos parmetros se pasan desde el procedimiento que llama al constructor; por ejemplo, Dim AnObject As New ThisClass(X).

Sub Finalize
Antes de liberar objetos, CLR llama automticamente al mtodo Finalize para los objetos que definen un procedimiento Sub Finalize.El mtodo Finalize puede contener cdigo que es necesario ejecutar inmediatamente antes de destruir un objeto, por ejemplo el cdigo para cerrar archivos y guardar

informacin de estado.Puesto que se produce una ligera disminucin del rendimiento al ejecutar Sub Finalize, este mtodo slo debe definirse cuando sea necesario liberar objetos explcitamente.

Nota
El recolector de elementos no utilizados de CLR no se deshace de los objetos no administrados (ni puede eliminarlos), que son aquellos que el sistema operativo ejecuta directamente, fuera del entorno de CLR.Esto se debe a que hay que deshacerse de los objetos no administrados diferentes de maneras distintas.Esa informacin no est asociada directamente al objeto no administrado; se debe buscar en la documentacin del objeto.Una clase que utiliza objetos no administrados debe deshacerse de ellos en su mtodo Finalize.

El destructor Finalize es un mtodo protegido al que slo se puede llamar desde la clase a la que pertenece o desde clases derivadas.El sistema llama automticamente a Finalize cuando se destruye un objeto, por lo que no se debe llamar explcitamente a Finalize desde fuera de una implementacin de su clase derivada. A diferencia de Class_Terminate, que se ejecuta en cuanto un objeto se establece en nothing, normalmente se suele producir un retraso desde que un objeto pierde el mbito hasta que Visual Basic llama al destructor Finalize.Visual Basic 2005 y versiones posteriores permiten un segundo tipo de destructor, Dispose, al que se puede llamar explcitamente en cualquier momento para liberar recursos inmediatamente.

Nota
Un destructor Finalize no debera producir excepciones porque la aplicacin no puede controlarlas y pueden hacer que la aplicacin finalice.

Cmo funcionan los mtodos New y Finalize en una jerarqua de clases


Siempre que se crea una instancia de una clase, Common Language Runtime (CLR) intenta ejecutar un procedimiento denominado New, si existe en ese objeto.New es un tipo de procedimiento denominado constructor que se usa para inicializar los objetos nuevos antes de que se ejecute cualquier otro cdigo en un objeto.Un constructor New puede utilizarse para abrir archivos, conectarse a bases de datos, inicializar variables y realizar cualquier otra tarea necesaria antes de poder utilizar un objeto. Cuando se crea una instancia de una clase derivada, se ejecuta primero el constructor Sub New de la clase base, seguido de los constructores de las clases derivadas.Esto se debe a que la primera lnea de cdigo en un constructor Sub New utiliza la sintaxis MyBase.New() para llamar al constructor de la clase situada inmediatamente por encima en la jerarqua de clases.Despus se llama al constructor Sub New para cada clase de la jerarqua hasta llegar al constructor de la clase base.En este punto, se ejecuta el cdigo del constructor para la clase base, seguido del cdigo en cada constructor de todas las clases derivadas, ejecutndose en ltimo lugar el cdigo de las clases ms derivadas.

Cuando un objeto deja de ser necesario, CLR llama al mtodo Finalize para ese objeto antes de liberar su memoria.El mtodo Finalize se denomina destructor porque realiza tareas de limpieza, como guardar informacin de estado, cerrar archivos y conexiones a bases de datos, y otras tareas que deben realizarse antes de liberar el objeto.

Interfaz IDisposable

A menudo, las instancias de clase controlan los recursos que no administra CLR, como identificadores de Windows y conexiones de bases de datos.Estos recursos se deben desechar en el mtodo Finalize de la clase, a fin de liberarlos cuando el recolector de elementos no utilizados destruya el objeto.Sin embargo, el recolector de elementos no utilizados slo destruye los objetos cuando CLR requiere ms memoria libre.Esto significa que los recursos pueden no liberarse hasta mucho despus de que el objeto salga del mbito. Para complementar la recoleccin de elementos no utilizados, las clases pueden proporcionar un mecanismo para administrar los recursos del sistema activamente si implementan la interfaz IDisposable.IDisposable tiene un mtodo, Dispose, al que deberan llamar los clientes cuando terminan de usar un objeto.Se puede utilizar el mtodo Dispose para liberar recursos inmediatamente y realizar tareas como cerrar archivos y conexiones de bases de datos.A diferencia del destructor Finalize, el mtodo Dispose no se llama automticamente.Los clientes de una clase deben llamar explcitamente a Dispose cuando se desea liberar recursos inmediatamente.

Implementar IDisposable
Una clase que implementa la interfaz IDisposable debera incluir estas secciones de cdigo:

Un campo para mantener el seguimiento de si se ha desechado el objeto:

Copiar Protected disposed As Boolean = False


Una sobrecarga de Dispose que libera los recursos de la clase.Los mtodos Dispose y Finalize de la clase base deben llamar a este mtodo:

Copiar Protected Overridable Sub Dispose(ByVal disposing As Boolean) If Not Me.disposed Then If disposing Then ' Insert code to free managed resources. End If ' Insert code to free unmanaged resources. End If Me.disposed = True End Sub
Una implementacin de Dispose que contiene slo el cdigo siguiente:

Copiar Public Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub
Un reemplazo del mtodo Finalize que contiene slo el cdigo siguiente:

Copiar Protected Overrides Sub Finalize() Dispose(False) MyBase.Finalize() End Sub

Derivar de una clase que implementa IDisposable


Una clase derivada de una clase base que implementa la interfaz IDisposable no necesita reemplazar ninguno de los mtodos base a menos que utilice recursos adicionales que se deban desechar.En esa situacin, la clase derivada debera reemplazar el mtodo Dispose(disposing) de la clase base para desechar los recursos de la clase derivada.Este reemplazo debe llamar al mtodo Dispose(disposing) de la clase base.

Copiar Protected Overrides Sub Dispose(ByVal disposing As Boolean) If Not Me.disposed Then If disposing Then ' Insert code to free managed resources. End If ' Insert code to free unmanaged resources. End If MyBase.Dispose(disposing) End Sub

Una clase derivada no debera reemplazar los mtodos Dispose y Finalize de la clase base.Cuando se llama a estos mtodos desde una instancia de una clase derivada, la implementacin de estos mtodos en la clase base llama al reemplazo del mtodo Dispose(disposing) en la clase derivada.

Recoleccin de elementos no utilizados y el destructor Finalize

.NET Framework utiliza el sistema de recoleccin de elementos no utilizados por traza de referencias para liberar peridicamente los recursos no utilizados.Visual Basic 6.0 y las versiones anteriores utilizaban un sistema diferente denominado recuento de referencias para administrar los recursos.Aunque ambos sistemas realizan la misma funcin automticamente, existen algunas diferencias importantes. CLR destruye peridicamente objetos cuando el sistema determina que ya no son necesarios.Los objetos se liberan con mayor rapidez cuando los recursos del sistema son escasos y con menor frecuencia en caso contrario.El retraso que se produce entre el momento en que un objeto pierde su mbito y el momento en que CLR lo libera significa que, a diferencia de lo que ocurre con los objetos en Visual Basic 6.0 y versiones anteriores, no se puede determinar exactamente cundo se destruir el objeto.En tal situacin, se dice que los objetos tienen duracin no determinista.En la mayora de los casos, la duracin no determinista no cambia la forma de escribir las aplicaciones, siempre que se recuerde que el destructor Finalize puede no ejecutarse inmediatamente cuando un objeto pierde su mbito. Otra diferencia entre los sistemas de recoleccin de elementos no utilizados tiene que ver con el uso de Nothing.Para aprovechar el recuento de referencias de Visual Basic 6.0 y versiones anteriores, los programadores a veces asignaban Nothing a variables de objeto para liberar las referencias que esas variables almacenaban.Si la variable almacenaba la ltima referencia al objeto, los recursos del objeto se liberaban inmediatamente.En las versiones posteriores de Visual Basic, aunque puede haber casos en los que este procedimiento sea an til, su realizacin nunca ocasionar que el objeto de referencia libere sus recursos inmediatamente.Para liberar inmediatamente los recursos, utilice el mtodo Dispose del objeto, si est disponible.La nica vez en que debe establecerse una variable en Nothing es cuando su duracin sea larga con relacin al tiempo que necesita el recolector de elementos no utilizados para detectar objetos hurfanos.

Cmo: Implementar el modelo DisposeFinalize (Visual Basic)


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007

El modelo DisposeFinalize garantiza que se liberan los recursos cuando ya no se necesita el objeto.

Ejemplo

La clase ResourceClass del ejemplo siguiente utiliza recursos administrados y no administrados y, a continuacin, utiliza el modelo DisposeFinalize para desecharlos correctamente. Los recursos y sus funciones son:

La implementacin del mtodo Dispose, que permite a los usuarios de la clase desechar las instancias de clase. Este mtodo llama a Dispose(True) para desechar los recursos del objeto y, a continuacin, llama a SuppressFinalize para evitar que el cdigo de finalizacin se ejecute una segunda vez. El reemplazo del mtodo base Finalize, que permite al recolector de elementos no utilizados de Common Language Runtime (CLR) desechar las instancias de clase. Este mtodo llama a Dispose(False) para desechar los recursos del objeto. Observe que si se llama a Dispose previamente para el objeto, su llamada a SuppressFinalize evitara que el recolector de elementos no utilizados llamase al mtodo Finalize. La sobrecarga del mtodo Dispose, que lleva a cabo el trabajo de eliminacin. Toma un parmetro de tipo Boolean, disposing, que indica si el cdigo ha iniciado la eliminacin del objeto. Cuando desecha un objeto, tambin se deben desechar todos sus recursos. Cuando el recolector de elementos no utilizados de CLR elimina un objeto, slo deben eliminarse los recursos no administrados; el recolector elimina automticamente los recursos administrados cuando resulta necesario.

Para obtener ms informacin, vea Duracin de los objetos: cmo se crean y destruyen.

VB C# C++ F# JScript

Copiar Public Class ResourceClass Implements IDisposable

Private managedResource As System.ComponentModel.Component Private unmanagedResource As IntPtr Protected disposed As Boolean = False

Public Sub New() ' Insert appropriate constructor code here. End Sub

Protected Overridable Overloads Sub Dispose( _ ByVal disposing As Boolean) If Not Me.disposed Then If disposing Then managedResource.Dispose() End If ' Add code here to release the unmanaged resource. unmanagedResource = IntPtr.Zero ' Note that this is not thread safe. End If Me.disposed = True End Sub

Public Sub AnyOtherMethods() If Me.disposed Then Throw New ObjectDisposedException(Me.GetType().ToString, _

"This object has been disposed.") End If End Sub

#Region " IDisposable Support " ' Do not change or add Overridable to these methods. ' Put cleanup code in Dispose(ByVal disposing As Boolean). Public Overloads Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub Protected Overrides Sub Finalize() Dispose(False) MyBase.Finalize() End Sub #End Region End Class

Este ejemplo de cdigo tambin est disponible como fragmento de cdigo de IntelliSense. En el selector de fragmentos de cdigo, se encuentra en Lenguaje Visual Basic. Para obtener ms informacin, vea Cmo: Insertar fragmentos de cdigo en el cdigo (Visual Basic).

Compilar el cdigo

Para este ejemplo se necesita:

Obtener acceso a los miembros de los espacios de nombres System y System.ComponentModel. Agregar una instruccin Imports si no se incluyen nombres de miembro completos en el cdigo. Para obtener ms informacin, vea Instruccin Imports (Tipo y espacio de nombres de .NET).

Estos cambios se deben realizar en el cdigo:

Reemplace ResourceClass con el nombre de la clase que implementa IDisposable. Utilice la comprobacin de AnyOtherMethods en cualquier mtodo que utilice recursos que se pueden haber desechado. Reemplace la declaracin managedResource con declaraciones de cualquier objeto administrado en su clase que deba ser desechado. Si una clase implementa IDisposable o tiene un mtodo Close, probablemente necesita ser desechado. En el mtodo Dispose, cierre o deseche estos objetos. Reemplace la declaracin unManagedResource con declaraciones de objetos no administrados en su clase que deban ser desechados. El mtodo para desechar estos objetos depende de cmo se define el objeto. Para obtener detalles, consulte la documentacin sobre el objeto.

Programacin eficaz

Cuando se ha llamado al mtodo Dispose, los objetos contenidos en su coleccin no sern vlidos. Debera probar el campo disposed antes de realizar cualquier operacin en su objeto. Para obtener un ejemplo, vea el mtodo AnyOtherMethods en el ejemplo de cdigo.

Utilizar constructores y destructores


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Los constructores y destructores controlan la creacin y destruccin de objetos.

Constructores

Para crear un constructor para una clase, cree un procedimiento denominado Sub New en cualquier parte de la definicin de clase. Para crear un constructor parametrizado, especifique los nombres y los tipos de datos de los argumentos de Sub New tal como lo hara en cualquier otro procedimiento, como en el cdigo siguiente:

VB C# C++ F# JScript

Copiar Sub New(ByVal s As String)

Con frecuencia, los constructores estn sobrecargados, como en el cdigo siguiente:

VB C# C++ F# JScript

Copiar Sub New(ByVal s As String, i As Integer)

Cuando se define una clase derivada de otra, la primera lnea del constructor debe ser una llamada al constructor de la clase base, a no ser que sta tenga un constructor accesible que no requiera parmetros. Por ejemplo, para llamar a la clase base que contiene el constructor anterior, sera MyBase.New(s). En caso contrario, MyBase.New es opcional y el tiempo de ejecucin de Visual Basic la llama implcitamente. Despus de escribir el cdigo para llamar al constructor del objeto primario, puede agregar cualquier cdigo de inicializacin adicional en el procedimiento Sub New. Sub New puede aceptar argumentos cuando se realiza la llamada como a un constructor con parmetros. Estos parmetros se pasan desde el procedimiento que llama al constructor; por ejemplo, Dim AnObject As New ThisClass(X).

Destructores

El cdigo siguiente muestra cmo utilizar Dispose y Finalize para liberar los recursos de una clase base.

Nota:
Debera seguir las instrucciones para implementar IDisposable incluidas en Duracin de los objetos: cmo se crean y destruyen.

VB C# C++

F# JScript

Copiar ' Design pattern for a base class. Public Class Base Implements IDisposable

' Keep track of when the object is disposed. Protected disposed As Boolean = False

' This method disposes the base object's resources. Protected Overridable Sub Dispose(ByVal disposing As Boolean) If Not Me.disposed Then If disposing Then ' Insert code to free managed resources. End If ' Insert code to free unmanaged resources. End If Me.disposed = True End Sub

#Region " IDisposable Support " ' Do not change or add Overridable to these methods. ' Put cleanup code in Dispose(ByVal disposing As Boolean).

Public Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub Protected Overrides Sub Finalize() Dispose(False) MyBase.Finalize() End Sub #End Region End Class

El cdigo siguiente muestra cmo utilizar Dispose y Finalize para liberar los recursos de una clase derivada.

VB C# C++ F# JScript

Copiar

' Design pattern for a derived class. Public Class Derived Inherits Base

' This method disposes the derived object's resources. Protected Overrides Sub Dispose(ByVal disposing As Boolean) If Not Me.disposed Then If disposing Then ' Insert code to free managed resources. End If ' Insert code to free unmanaged resources. End If MyBase.Dispose(disposing) End Sub

' The derived class does not have a Finalize method ' or a Dispose method with parameters because it inherits ' them from the base class. End Class

El cdigo siguiente muestra un modelo de diseo comn para el destructor Dispose, utilizando un bloque Using y un bloque Try...Finally equivalente.

VB

C# C++ F# JScript

Copiar Sub DemonstrateUsing() Using d As New Derived ' Code to use the Derived object goes here. End Using End Sub

Sub DemonstrateTry() Dim d As Derived = Nothing Try d = New Derived ' Code to use the Derived object goes here. Finally ' Call the Dispose method when done, even if there is an exception. If Not d Is Nothing Then d.Dispose() End If End Try End Sub

En el siguiente ejemplo se crea un objeto mediante un constructor con parmetros y se llama a los destructores cuando el objeto deja de ser necesario.

Nota:
Aunque este ejemplo usa Collect para mostrar a qu mtodos llama el recolector de elementos no utilizados para eliminar mtodos, en general es ms conveniente dejar que Common Language Runtime (CLR) administre la recoleccin de elementos no utilizados.

VB C# C++ F# JScript

Copiar Sub TestConstructorsAndDestructors() ' Demonstrate how the Using statement calls the Dispose method. Using AnObject As New ThisClass(6) ' Place statements here that use the object. MsgBox("The value of ThisProperty after being initialized " & _ " by the constructor is " & AnObject.ThisProperty & ".") End Using

' Demonstrate how the garbage collector calls the Finalize method. Dim AnObject2 As New ThisClass(6) AnObject2 = Nothing GC.Collect() End Sub

Public Class BaseClass Sub New() MsgBox("BaseClass is initializing with Sub New.") End Sub

Protected Overrides Sub Finalize() MsgBox("BaseClass is shutting down with Sub Finalize.") ' Place final cleanup tasks here. MyBase.Finalize() End Sub End Class

Public Class ThisClass Inherits BaseClass Implements IDisposable

Sub New(ByVal SomeValue As Integer) ' Call MyBase.New if this is a derived class. MyBase.New() MsgBox("ThisClass is initializing with Sub New.") ' Place initialization statements here.

ThisPropertyValue = SomeValue End Sub

Private ThisPropertyValue As Integer Property ThisProperty() As Integer Get CheckIfDisposed() ThisProperty = ThisPropertyValue End Get Set(ByVal Value As Integer) CheckIfDisposed() ThisPropertyValue = Value End Set End Property

Protected Overrides Sub Finalize() MsgBox("ThisClass is shutting down with Sub Finalize.") Dispose(False) End Sub

' Do not add Overridable to this method. Public Overloads Sub Dispose() Implements IDisposable.Dispose MsgBox("ThisClass is shutting down with Sub Dispose.") Dispose(True) GC.SuppressFinalize(Me) End Sub

Private disposed As Boolean = False

Public Sub CheckIfDisposed() If Me.disposed Then Throw New ObjectDisposedException(Me.GetType().ToString, _ "This object has been disposed.") End If End Sub

Protected Overridable Overloads Sub Dispose( _ ByVal disposing As Boolean) MsgBox("ThisClass is shutting down with the Sub Dispose overload.") ' Place final cleanup tasks here. If Not Me.disposed Then If disposing Then ' Dispose of any managed resources. End If ' Dispose of any unmanaged resource.

' Call MyBase.Finalize if this is a derived class, ' and the base class does not implement Dispose. MyBase.Finalize() End If Me.disposed = True End Sub

End Class

Cuando ejecute este ejemplo, la clase ThisClass llama al constructor Sub New de la clase BaseClass. Una vez que finaliza el constructor de la clase base, la clase ThisClass ejecuta el resto de instrucciones de Sub New que inicializan un valor para la propiedad ThisProperty. Cuando la clase ya no es necesaria, se llama al destructor Dispose en ThisClass. Este ejemplo muestra lo siguiente: BaseClass is initializing with Sub New. ThisClass is initializing with Sub New. The value of ThisProperty after being initialized by the constructor is 6. ThisClass is shutting down with Sub Dispose. ThisClass is shutting down with the Sub Dispose overload. BaseClass is shutting down with Sub Finalize. BaseClass is initializing with Sub New. ThisClass is initializing with Sub New. ThisClass is shutting down with Sub Finalize. ThisClass is shutting down with the Sub Dispose overload. BaseClass is shutting down with Sub Finalize.

Cmo: Agregar campos y propiedades a una clase


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Se pueden utilizar tanto campos como propiedades para almacenar informacin en un objeto. Aunque los campos y las propiedades son muy difciles de distinguir desde una perspectiva de aplicacin de cliente, se declaran de forma diferente en una clase. Mientras que los campos son simplemente variables

pblicas que una clase expone, las propiedades utilizan procedimientos Property para controlar cmo se establecen y devuelven valores.

Para agregar un campo a una clase

Declare una variable pblica en la definicin de clase, como en el cdigo siguiente:

VB C# C++ F# JScript

Copiar Class ThisClass Public ThisField As String End Class

Para agregar una propiedad a una clase


1. Declare una variable local en la clase para almacenar el valor de la propiedad. Este paso es necesario puesto que las propiedades no asignan almacenamiento por s mismas. A fin de proteger sus valores contra la modificacin directa, las variables que se utilizan para almacenar valores de propiedad deben declarase como Private.

2.

3.

4. 5.

Escriba modificadores antes de las declaraciones de propiedad, como Public y Shared, segn corresponda. Utilice la palabra clave Property para declarar el nombre de la propiedad y declare el tipo de datos que la propiedad almacena y devuelve. Defina los procedimientos de propiedad Get y Set dentro de la definicin de propiedad. Los procedimientos de propiedad Get se utilizan para devolver el valor de una propiedad y son aproximadamente equivalentes a las funciones de sintaxis. No aceptan ningn argumento y se pueden utilizar para devolver el valor de variables local privadas declaradas dentro de la clase utilizada para almacenar el valor de la propiedad. Los procedimientos de propiedad Set se utilizan para establecer el valor de una propiedad; tienen un parmetro, llamado normalmente Value, con el mismo tipo de datos que la propiedad en s. Cada vez que se cambia el valor de la propiedad, se pasa Value al procedimiento de propiedad Set, donde se puede validar y almacenar en una variable local. Finalice los procedimientos de propiedad Get y Set con las instrucciones End Get y End Set correspondientes. Finalice el bloque de propiedad con una instruccin End Property.

Nota:
Si est trabajando dentro del entorno de desarrollo integrado (IDE) de Visual Studio, puede dirigirlo para crear procedimientos de propiedad Get y Set vacos. Escriba Property NombreProp As TipoDeDatos (donde NombreProp es el nombre de la propiedad y TipoDeDatos es un tipo de datos especfico, por ejemplo Integer), y los procedimientos de propiedad aparecen en el Editor de cdigo.

6.

En el siguiente ejemplo se declara una propiedad en una clase:

7.

8. 9. 10. 11. 12.

VB C# C++ F# JScript

13.

14. Copiar

15. Class ThisClass 16. Private m_PropVal As String 17. Public Property One() As String 18. Get 19. ' Return the value stored in the local variable. 20. Return m_PropVal

21. End Get 22. Set(ByVal Value As String) 23. ' Store the value in a local variable. 24. m_PropVal = Value 25. End Set 26. End Property 27. End Class 28. 29. 30. Cuando se crea una instancia de ThisClass y se establece el valor de la propiedad One, se llama al procedimiento de propiedad Set y se pasa el valor en el parmetro Value, que se almacena en una variable local denominada m_PropVal. Cuando se recupera el valor de esta propiedad, se llama al procedimiento de propiedad Get como funcin y devuelve el valor almacenado en la variable local m_PropVal.

Propiedades y procedimientos de propiedad


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Se pueden utilizar tanto propiedades como campos para almacenar informacin en un objeto. Mientras que los campos son simplemente variables pblicas, las propiedades utilizan procedimientos de propiedad para controlar cmo se establecen y devuelven valores. Los procedimientos de propiedad son bloques de cdigo declarados dentro de las definiciones de propiedad que puede ejecutar cdigo cuando se establece o recupera el valor de una propiedad. Visual Basic tiene dos tipos de procedimientos de propiedad: los procedimientos de propiedad Get para recuperar un valor de una propiedad y los procedimientos de propiedad Set para asignar un valor a una propiedad. Por ejemplo, una propiedad que almacena el saldo de una cuenta bancaria podra utilizar cdigo en un procedimiento de propiedad Get para notificar el inters y comprobar comisiones por servicios antes de devolver el saldo disponible. Puede utilizar luego el procedimiento de propiedad Set para validar el balance y evitar que se actualice incorrectamente. Es decir, los procedimientos de propiedad permiten a un objeto proteger y validar sus propios datos. En el siguiente fragmento de cdigo se compara el modo en el que los campos y propiedades validan los valores.

VB C# C++ F# JScript

Copiar Protected Sub TestFieldsAndProperties() ' Assume, for this example, that the only valid values for ' the field and property are numbers less than 10. Dim NewClass As New ThisClass

' Test data validation.

' Works because there is no data validation. NewClass.ThisField = 36 ' Will print 36. MsgBox("ThisField = " & NewClass.ThisField)

' The attempt to set the field to a value greater than 10 will silently fail. NewClass.ThisProperty = 36

' The next statement will print the old value of 0 instead. MsgBox("ThisProperty = " & NewClass.ThisProperty) End Sub

Public Class ThisClass ' Declare a field. Public ThisField As Integer ' Field used for Property Set operations. Private thisPropertyValue As Integer = 0 ' Declare a property. Public Property ThisProperty() As Integer Get Return thisPropertyValue End Get Set(ByVal Value As Integer) ' Only allow Set operation for values less than 10. If Value < 10 Then thisPropertyValue = Value End Set End Property End Class

El procedimiento TestFieldsAndProperties crea una instancia de la clase, y establece y recupera los valores de los campos y propiedades. En este ejemplo se asume que los nicos valores vlidos son nmeros menores de 10. Dado que no hay forma de validar los valores asignados a los campos, es posible establecer en el campo el valor 36. No obstante, la propiedad solamente realiza asignaciones para nmeros menores de 10, de modo que el intento de establecer 36 en el campo no se tiene en cuenta.

Propiedades de slo lectura y escritura

La mayora de las propiedades tienen procedimientos de propiedad Get y Set que puede utilizar para leer y modificar el valor que almacenan. No obstante, puede utilizar los modificadores ReadOnly y WriteOnly para restringir la modificacin o la lectura de las propiedades. Las propiedades de slo lectura no pueden tener procedimientos de propiedad Set; estas propiedades son tiles para elementos que desea exponer, pero cuya modificacin no desea permitir. Por ejemplo, podra utilizar una propiedad de slo lectura para proporcionar la velocidad del procesador de un equipo. Las propiedades de slo escritura no pueden tener procedimientos de propiedad Get y son tiles para configurar objetos con datos que no deben o no se pueden almacenar en el objeto. Por ejemplo, se puede utilizar una propiedad de slo escritura para tomar una contrasea y cambiar el estado del objeto sin almacenar la contrasea.

Nota:
Las versiones anteriores de Visual Basic admiten procedimientos de propiedad Let que se utilizan al asignar objetos a las propiedades. Visual Basic elimina la necesidad de procedimientos de propiedad Let porque la asignacin de objetos se controla como cualquier otro tipo de asignacin.

Comparacin de procedimientos de propiedades y campos


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Las propiedades y los campos ambos almacenan y recuperan informacin en un objeto. Dada su similitud, resulta difcil determinar cul es la mejor opcin de programacin en casos concretos. Utilice procedimientos de propiedad cuando:

Necesite controlar cundo y cmo se establece o recupera un valor. La propiedad tenga un conjunto de valores bien definidos que no necesiten validacin.

El establecimiento del valor genera algn cambio perceptible en el estado del objeto, como una propiedad IsVisible. El establecimiento de la propiedad ocasione cambios en otras variables internas o en los valores de otras propiedades. Deban ejecutarse un conjunto de pasos antes de poder establecer o recuperar la propiedad.

Utilice campos cuando:

El valor sea de un tipo de autovalidacin. Por ejemplo, si un valor distinto de True o False se asigna a una variable Boolean, se produce un error o una conversin de datos automtica. Sea vlido cualquier valor del intervalo admitido por el tipo de datos. Esto es verdadero en muchas propiedades de tipo Single o Double. La propiedad sea un tipo de datos String y no existan restricciones en cuanto al tamao o al valor de la cadena.

Mtodos de una clase


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Los mtodos de una clase son simplemente procedimientos Sub o Function declarados dentro de la clase. Por ejemplo, para crear un mtodo Withdrawal para una clase denominada Account, se podra agregar la funcin Public al mdulo de la clase:

VB C# C++ F# JScript

Copiar Public Function WithDrawal(ByVal Amount As Decimal, _ ByVal TransactionCode As Byte) As Double ' Add code here to perform the withdrawal, ' return a transaction code, ' or to raise an overdraft error. End Function

Mtodos compartidos

Los mtodos compartidos pueden llamarse directamente desde la clase sin necesidad de crear previamente una instancia de la clase. Los mtodos compartidos son tiles cuando se desea asociar un mtodo con una instancia especfica de una clase. Los mtodos compartidos no se pueden declarar mediante los modificadores Overridable, NotOverridable o MustOverride. Los mtodos que se declaran en mdulos estn compartidos implcitamente y no pueden utilizar el modificador Shared explcitamente.

Ejemplo

VB C# C++ F#

JScript

Copiar Class ShareClass Shared Sub SharedSub() MsgBox("Shared method.") End Sub End Class

Sub Test() ' Call the method. ShareClass.SharedSub() End Sub

Proteccin de los detalles de la implementacin

Los procedimientos de utilidades empleados internamente por una clase se deben declarar como Private, Protected o Friend. La restriccin de la accesibilidad de tales mtodos protege a los desarrolladores que utilizan sus objetos, ya que le permite realizar futuros cambios sin que afecte al cdigo que utiliza los objetos. La proteccin de los detalles de la implementacin de un objeto es otra faceta de la encapsulacin. La encapsulacin permite mejorar el rendimiento de los mtodos o cambiar totalmente la forma de implementar un mtodo, sin necesidad de modificar el cdigo que utiliza el mtodo.

Propiedades frente a mtodos


Visual Studio 2008

Otras versiones

Actualizacin: noviembre 2007 Las propiedades y los mtodos son similares en que ambos se implementan como procedimientos que aceptan argumentos. En general, las propiedades almacenan datos para un objeto, y los mtodos son acciones cuya realizacin puede pedirse a un objeto. Algunas caractersticas de objeto son claramente propiedades, como Name, mientras que otras son evidentemente mtodos, como Move y Show. En otros casos, no resulta obvio qu miembros de una clase deberan ser propiedades y cules deberan ser mtodos. Por ejemplo, el mtodo Item de una clase de coleccin almacena y recupera datos, y puede implementarse como una propiedad indizada. Por otra parte, tambin resulta razonable implementar Item como un mtodo.

Sintaxis de propiedades frente a sintaxis de mtodos

Una forma de decidir cmo implementar un miembro de una clase consiste en considerar cmo se desea utilizar. Aunque la sintaxis para recuperar informacin de una propiedad parametrizada es casi idntica a la utilizada con un mtodo implementado como funcin, la sintaxis para modificar tal valor es algo diferente. Por ejemplo, si implementa el miembro de una clase como propiedad, la sintaxis siguiente describe cmo debera utilizarse: Objeto.Propiedad(ndice) = NuevoValor Si implementa el miembro de la clase como mtodo, el valor que se modifica debe ser un argumento. El fragmento de cdigo siguiente describe el uso de sintaxis equivalente: Objeto.Propiedad(ndice, NuevoValor)

Mensajes de error

Otro factor a considerar a la hora de elegir cmo implementar un miembro de una clase es qu tipo de mensajes se generarn cuando la clase se utilice incorrectamente. Si alguien intenta accidentalmente asignar un valor a una propiedad de slo lectura, el mensaje de error devuelto es distinto del que se obtendra en respuesta a una llamada similar a un mtodo. Los miembros de una clase implementados correctamente devuelven mensajes de error que son ms fciles de interpretar.

Propiedades predeterminadas
Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Una propiedad que acepta argumentos puede declararse como propiedad predeterminada de una clase. Una propiedad predeterminada es aquella que utiliza Visual Basic cuando no se haya asignado una propiedad especfica para un objeto. Las propiedades predeterminadas son tiles porque permiten que el cdigo fuente sea ms compacto al omitirse nombres de propiedades que se utilizan frecuentemente. Las mejores candidatas a propiedades predeterminadas son las propiedades que aceptan parmetros y que se utilizarn con ms frecuencia. Por ejemplo, la propiedad Item es una buena opcin como propiedad predeterminada de una clase de coleccin, ya que se usa con frecuencia. Las siguientes reglas se aplican a las propiedades predeterminadas:

Un tipo slo puede tener una propiedad predeterminada, incluyendo las propiedades heredadas de una clase base. Hay una excepcin para esta regla. Una propiedad predeterminada definida en una clase base puede ser sombreada por otra propiedad predeterminada de una clase derivada. Si una propiedad predeterminada de una clase base es sombreada por una propiedad no predeterminada de una clase derivada, la propiedad predeterminada contina permitiendo el acceso mediante la sintaxis de propiedad predeterminada. Una propiedad predeterminada no puede ser de tipo Shared o Private. Si una propiedad sobrecargada es una propiedad predeterminada, tambin lo sern todas las dems propiedades sobrecargadas que tengan el mismo nombre. Las propiedades predeterminadas deben aceptar al menos un argumento.

Ejemplo

El siguiente ejemplo declara una propiedad que contiene una matriz de cadenas como propiedad predeterminada de una clase:

VB C# C++ F# JScript

Copiar Class Class2 ' Define a local variable to store the property value. Private PropertyValues As String() ' Define the default property. Default Public Property Prop1(ByVal Index As Integer) As String Get Return PropertyValues(Index) End Get Set(ByVal Value As String) If PropertyValues Is Nothing Then ' The array contains Nothing when first accessed. ReDim PropertyValues(0) Else ' Re-dimension the array to hold the new element. ReDim Preserve PropertyValues(UBound(PropertyValues) + 1) End If PropertyValues(Index) = Value End Set

End Property End Class

Acceso a propiedades predeterminadas

El acceso a propiedades predeterminadas puede realizarse mediante sintaxis abreviada. Por ejemplo, en el fragmento de cdigo siguiente se utiliza sintaxis estndar y sintaxis predeterminada:

VB C# C++ F# JScript

Copiar Dim C As New Class2 ' The first two lines of code access a property the standard way.

' Property assignment. C.Prop1(0) = "Value One" ' Property retrieval.

MsgBox(C.Prop1(0))

' The following two lines of code use default property syntax.

' Property assignment. C(1) = "Value Two" ' Property retrieval. MsgBox(C(1))

Propiedades y mtodos sobrecargados (Visual Basic)


Visual Studio 2010 Otras versiones

La sobrecarga consiste en crear ms de un procedimiento, constructor de instancia o propiedad en una clase con el mismo nombre y distintos tipos de argumento.

Uso de la sobrecarga

La sobrecarga es especialmente til cuando un modelo de objeto exige el uso de nombres idnticos para procedimientos que operan en diferentes tipos de datos.Por ejemplo, una clase que puede mostrar diferentes tipos de datos podra tener procedimientos Display como los siguientes:

VB C#

C++ F# JScript

Copiar

Overloads Sub Display(ByVal theChar As Char) ' Add code that displays Char data. End Sub Overloads Sub Display(ByVal theInteger As Integer) ' Add code that displays Integer data. End Sub Overloads Sub Display(ByVal theDouble As Double) ' Add code that displays Double data. End Sub

Sin sobrecarga, sera necesario crear distintos nombres para cada procedimiento, aunque realicen el mismo cometido, como se muestra a continuacin:

VB C#

C++ F# JScript

Copiar

Sub DisplayChar(ByVal theChar As Char) ' Add code that displays Char data. End Sub Sub DisplayInt(ByVal theInteger As Integer) ' Add code that displays Integer data. End Sub Sub DisplayDouble(ByVal theDouble As Double) ' Add code that displays Double data. End Sub

La sobrecarga facilita el uso de propiedades o mtodos, puesto que ofrece una seleccin de tipos de datos que se pueden utilizar.Por ejemplo, se pude llamar al mtodo sobrecargado Display descrito anteriormente con cualquiera de las siguientes lneas de cdigo:

VB C#

C++ F# JScript

Copiar

' Call Display with a literal of type Char. Display("9"c) ' Call Display with a literal of type Integer. Display(9) ' Call Display with a literal of type Double. Display(9.9R)

En tiempo de ejecucin, Visual Basic llama al procedimiento correcto basndose en los tipos de datos de los parmetros que se han especificado.

Reglas de sobrecarga

Es posible crear un miembro sobrecargado para una clase agregando dos o ms propiedades o mtodos con el mismo nombre.A excepcin de los miembros derivados sobrecargados, cada miembro sobrecargado debe tener distintas listas de parmetros, y los elementos que a continuacin se enumeran, no se pueden utilizar como caractersticas diferenciadoras al sobrecargar una propiedad o un procedimiento:

Modificadores, como por ejemplo ByVal o ByRef, que se aplican a un miembro o parmetros de un miembro. Nombres de parmetros Tipos de valores devueltos de procedimientos

La palabra clave Overloads es opcional en la sobrecarga, aunque si algn miembro sobrecargado la utiliza, todos los dems miembros sobrecargados con el mismo nombre deben especificarla tambin. Las clases derivadas pueden sobrecargar miembros heredados con miembros que tengan idnticos parmetros y tipos de parmetros, un proceso denominado sombrear por nombre y firma.Si se utiliza la palabra clave Overloads al sombrear por nombre y firma, se utilizar la implementacin de la clase derivada del miembro en vez de la implementacin de la clase base y todas las dems sobrecargas de dicho miembro estarn disponibles para las instancias de la clase derivada. Si se omite la palabra clave Overloads al sobrecargar un miembro heredado con un miembro que tiene parmetros y tipos de parmetros idnticos, la sobrecarga se denomina sombrear por nombre.El proceso sombrear por nombre reemplaza a la implementacin heredada de un miembro y hace que todas las dems sobrecargas no estn disponibles para las instancias de la clase derivada y sus descendientes. Los modificadores Overloads y Shadows no pueden utilizarse a la vez con la misma propiedad o mtodo.

Ejemplo
El ejemplo siguiente crea mtodos sobrecargados que aceptan una representacin String o Decimal de una cantidad en dlares y devuelven una cadena que contiene los impuestos sobre ventas.

Para utilizar este ejemplo para crear un mtodo sobrecargado


1. 2. Abra un nuevo proyecto y agregue una clase denominada TaxClass. Agregue el cdigo siguiente a la clase TaxClass.

VB C# C++ F# JScript

Copiar

Public Class TaxClass Overloads Function TaxAmount(ByVal decPrice As Decimal, ByVal TaxRate As Single) As String TaxAmount = "Price is a Decimal. Tax is $" & (CStr(decPrice * TaxRate)) End Function

Overloads Function TaxAmount(ByVal strPrice As String, ByVal TaxRate As Single) As String TaxAmount = "Price is a String. Tax is $" & CStr((CDec(strPrice) * TaxRate)) End Function End Class

3.

Agregue el procedimiento siguiente a su formulario.

VB

C# C++ F# JScript

Copiar

Sub ShowTax() ' 8% tax rate. Const TaxRate As Single = 0.08 ' $64.00 Purchase as a String. Dim strPrice As String = "64.00" ' $64.00 Purchase as a Decimal. Dim decPrice As Decimal = 64 Dim aclass As New TaxClass 'Call the same method with two different kinds of data. MsgBox(aclass.TaxAmount(strPrice, TaxRate)) MsgBox(aclass.TaxAmount(decPrice, TaxRate)) End Sub

4. 5.

Agregue un botn al formulario y llame al procedimiento ShowTax desde el evento Button1_Click del botn. Ejecute el proyecto y haga clic en el botn del formulario para probar el procedimiento sobrecargado ShowTax.

En tiempo de ejecucin, el compilador elige la funcin sobrecargada adecuada que coincida con los parmetros que se utilicen.Al hacer clic en el botn, primero se llama al mtodo sobrecargado con un parmetro Price que es una cadena y se muestra el mensaje: "Price is a String.Tax is $5.12".La segunda vez, se llama a TaxAmount con un valor Decimal y se muestra el mensaje, "Price is a Decimal.Tax is $5.12".

Invalidar propiedades y mtodos


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Una clase derivada hereda las propiedades y mtodos definidos en su clase base. Esto es til porque puede reutilizar estos elementos cuando son adecuados para la clase derivada. Si la propiedad o mtodo en la clase base est marcada con la palabra clave Overridable, puede definir una nueva implementacin para el miembro en la clase derivada. Utilice la palabra clave Overrides para sombrear el miembro volvindolo a definir en la clase derivada. Esto es til cuando no puede utilizar el miembro "tal cual". En la prctica, los miembros reemplazados suelen utilizarse para implementar el polimorfismo. Para obtener ms informacin, consulte Polimorfismo. Las siguientes reglas se aplican a los mtodos de reemplazo.

Slo se pueden reemplazar miembros que estn marcados con la palabra clave Overridable en la clase base. De forma predeterminada, las propiedades y los mtodos son NotOverridable. Los miembros reemplazados deben tener los mismos argumentos que los miembros heredados de la clase base. La nueva implementacin de un miembro puede llamar a la implementacin original de la clase primaria mediante la especificacin de MyBase antes del nombre de mtodo.

Nota:
La sobrecarga, el reemplazo y el sombreado son conceptos similares que pueden confundirse fcilmente. Para obtener ms informacin, consulte Introduccin a los objetos en Visual Basic.

Ejemplo

Suponga que desea definir clases para controlar la nmina. Podra definir una clase genrica Payroll que contenga un mtodo RunPayroll para calcular la nmina de una semana tpica. Podra utilizar Payroll como clase base de una clase ms especializada BonusPayroll que se utilizara para distribuir bonificaciones entre los empleados. La clase BonusPayroll puede heredar y reemplazar al mtodo PayEmployee definido en la clase base Payroll. En el siguiente ejemplo se define una clase base, Payroll, y una clase derivada, BonusPayroll, que reemplaza a un mtodo heredado, PayEmployee. Un procedimiento, RunPayroll crea y luego pasa un objeto Payroll y un objeto BonusPayroll a una funcin, Pay, que ejecuta el mtodo PayEmployee de ambos objetos.

VB C# C++ F# JScript

Copiar Const BonusRate As Decimal = 1.45D Const PayRate As Decimal = 14.75D

Class Payroll Overridable Function PayEmployee( _ ByVal HoursWorked As Decimal, _

ByVal PayRate As Decimal) _ As Decimal

PayEmployee = HoursWorked * PayRate End Function End Class

Class BonusPayroll Inherits Payroll Overrides Function PayEmployee( _ ByVal HoursWorked As Decimal, _ ByVal PayRate As Decimal) _ As Decimal

' The following code calls the original method in the base ' class, and then modifies the returned value. PayEmployee = MyBase.PayEmployee(HoursWorked, PayRate) * BonusRate End Function End Class

Sub RunPayroll() Dim PayrollItem As Payroll = New Payroll Dim BonusPayrollItem As New BonusPayroll Dim HoursWorked As Decimal = 40

MsgBox("Normal pay is: " & _ PayrollItem.PayEmployee(HoursWorked, PayRate)) MsgBox("Pay with bonus is: " & _

BonusPayrollItem.PayEmployee(HoursWorked, PayRate)) End Sub

Crear y utilizar objetos


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Los objetos son combinaciones de cdigo y datos que pueden tratarse como unidades individuales. Prcticamente todas las actividades que se realizan en Visual Basic implican el uso de objetos, desde los controles que se utilizan hasta los formularios en los que se colocan. En esta seccin se explica dnde se originan los objetos y la forma de utilizarlos.

Objetos de Visual Basic y otros orgenes


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Los objetos que se utilizan en Visual Basic proceden de orgenes internos y externos. Entre los ejemplos de objetos internos se incluyen los objetos y clases intrnsecos en el proyecto; entre los ejemplos de objeto externos se incluyen los ensamblados y los objetos COM.

Objetos internos

Los objetos intrnsecos (o integrados) son los que proporciona Visual Basic de forma nativa. Entre stos se incluyen los tipos escalares primitivos como Integer y Double, as como los tipos Array y String. No hace falta crear referencias a objetos internos antes de utilizarlos en el proyecto. Otros objetos internos son instancias de clases en el proyecto actual. Estas clases pueden utilizarse siempre que sean necesarias dentro del proyecto y pueden estar disponibles para otras aplicaciones cuando se crea un ensamblado.

Objetos externos

Los objetos externos son los que proceden de otros proyectos o ensamblados que no estn disponibles en el proyecto de manera predeterminada. Es necesario crear referencias de proyecto a los objetos externos para poder utilizarlos en el proyecto. Los ensamblados son el origen ms comn de objetos para las aplicaciones de Visual Basic. .NET Framework incluye ensamblados que contienen objetos que se utilizan habitualmente. Algunos objetos en .NET Framework se tratan como objetos intrnsecos, pero la mayora de los ensamblados deben importarse de forma explcita mediante la instruccin Imports antes de poder utilizarlos. Cualquier lenguaje compatible con Common Language Specification (CLS), como Visual Basic o Visual C#, puede crear y utilizar ensamblados. Para obtener ms informacin, consulte Ensamblados. En el pasado, los componentes COM eran el origen tradicional de objetos para programadores de Visual Basic, pero actualmente los ensamblados de .NET Framework constituyen una opcin mejor para los nuevos objetos. Todava se pueden utilizar los componentes COM existentes en las aplicaciones; no obstante, el acceso a los objetos COM debe realizarse mediante clases de interoperabilidad de .NET Framework. El acceso a una biblioteca COM requiere el uso de un ensamblado de interoperabilidad que contenga clases de interoperabilidad para cada clase COM definida en la biblioteca. Para obtener ms informacin, consulte Interoperabilidad COM. Adems de tener acceso a las clases de .NET Framework nativas y las clases COM, tambin es posible llamar a las funciones definidas en bibliotecas de vnculos dinmicos (archivos DLL), como las de la API Win32. Visual Basic le permite llamar a las funciones en archivos DLL una vez que se hayan declarado con una instruccin Declare. Visual Basic agrega la funcionalidad a la instruccin Declare y le permite utilizar el atributo DllImportAttribute para especificar valores predeterminados para elementos como CallingConvention, ExactSpelling y SetLastError. Los parmetros de instrucciones Declare pueden anotarse con el atributo MarshalAsAttribute, que admite la conversin de parmetros en formas que no eran posibles en versiones anteriores de Visual Basic.

Cmo: Establecer y recuperar propiedades


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Las propiedades de formularios y controles en Visual Basic pueden establecerse mediante programacin en tiempo de ejecucin o en modo de diseo en la ventana Propiedades. Las propiedades de la mayora de los objetos restantes, como los objetos de los ensamblados o los objetos que haya creado, nicamente pueden establecerse mediante programacin. Las propiedades que se pueden establecer y leer se denominan propiedades de lectura y escritura. Las propiedades que se pueden leer pero no modificar se denominan propiedades de slo lectura. Las propiedades en las que se puede escribir pero que no se pueden leer se denominan propiedades de slo escritura. El valor de una propiedad se establece cuando se desea modificar el aspecto o el comportamiento de un objeto. Por ejemplo, la propiedad Text de un control de cuadro de texto se cambia para modificar el contenido del cuadro de texto. El valor de una propiedad se obtiene cuando se desea conocer el estado de un objeto antes de que el cdigo ejecute acciones adicionales, tales como asignar el valor a otro objeto. Por ejemplo, se puede devolver la propiedad Text de un control de cuadro de texto para determinar el contenido del cuadro de texto antes de ejecutar un cdigo que podra modificar el valor.

Para establecer valores de propiedad

Utilice la sintaxis siguiente: Objeto.propiedad=expresin Las instrucciones siguientes proporcionan ejemplos sobre cmo establecer propiedades:

VB C# C++

F# JScript

Copiar ' Set the Top property to 200 twips. TextBox1.Top = 200 ' Display the text box. TextBox1.Visible = True ' Display 'hello' in the text box. TextBox1.Text = "hello"

Nota:
Tambin puede establecer una propiedad pasndola a parmetros ByRef, en cuyo caso la propiedad queda modificada por el resultado devuelto por el parmetro ByRef.

Para obtener valores de propiedad

Utilice la sintaxis siguiente: variable=Objeto.propiedad Tambin puede obtener un valor de propiedad como parte de una expresin ms compleja, sin asignar la propiedad a una variable. El siguiente cdigo modifica la propiedad Top de un control de botn de opcin:

VB C# C++ F# JScript

Copiar RadioButton1.Top += 20

Cmo: Realizar acciones con mtodos


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007

Los mtodos son procedimientos asociados a objetos. Excepto los campos y las propiedades, que representan informacin que puede almacenar un objeto, los mtodos representan acciones que puede realizar un objeto. Los mtodos pueden afectar a los valores de las propiedades. Por ejemplo, en el caso de una analoga de radio, se puede emplear un mtodo SetVolume para cambiar el valor de una propiedad Volume. De igual forma, en Visual Basic, los elementos de cuadros de lista tienen una propiedad List que puede cambiar con los mtodos Clear y Add. Al utilizar un mtodo en cdigo, la forma de crear la instruccin depende de cuntos argumentos requiere el mtodo y de si devuelve un valor. Generalmente, los mtodos se utilizan igual que las subrutinas o las llamadas de funcin. De forma ms especfica, los mtodos se invocan del mismo modo que los procedimientos de mdulos, exceptuando que los mtodos se pueden calificar con una expresin especificando la instancia del objeto a cuyo mtodo debe llamarse. Si no est calificada, la instancia es de forma implcita la variable Me.

Para utilizar un mtodo que no requiera argumentos

Utilice la sintaxis siguiente: Objeto.mtodo() En el ejemplo siguiente, el mtodo Refresh vuelve a dibujar el cuadro de imagen:

VB C# C++ F# JScript

Copiar ' Force the control to repaint.

PictureBox1.Refresh()

Nota:
Algunos mtodos, como Refresh, no tienen argumentos y no devuelven valores.

Para utilizar un mtodo que requiera varios argumentos

Ponga los argumentos entre parntesis y seprelos mediante comas. En el ejemplo siguiente, el mtodo MsgBox utiliza argumentos que especifican el mensaje que se debe mostrar y el estilo del cuadro de mensaje:

VB C# C++ F# JScript

Copiar MsgBox("Database update complete", _ MsgBoxStyle.OKOnly Or MsgBoxStyle.Exclamation, _ "My Application")

Para utilizar un mtodo que devuelva un valor

Asigne el valor devuelto a una variable o utilice directamente la llamada al mtodo como parmetro para otra llamada. El cdigo siguiente almacena el valor devuelto:

VB C# C++ F# JScript

Copiar Dim Response As MsgBoxResult Response = MsgBox("Do you want to exit?", _ MsgBoxStyle.YesNo Or MsgBoxStyle.Question, _ "My Application")

Este ejemplo utiliza el valor devuelto desde el mtodo Len como un argumento para MsgBox.

VB C# C++ F# JScript

Copiar Dim TestStr As String = "Some String" ' Display the string "String length is : 11". MsgBox("String length is : " & Len(TestStr))

Cmo: Tratar formularios como objetos


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Los formularios son objetos grficos que componen la interfaz de usuario de una aplicacin. Dentro de Visual Basic, las clases definen cmo se muestran los formularios y qu pueden hacer. Cuando se muestra un formulario en tiempo de ejecucin, Visual Basic crea una instancia de la clase Form que se puede utilizar como cualquier otro objeto. Puede agregar propiedades y mtodos personalizados a formularios y tener acceso a ellos desde otros formularios o clases de la aplicacin.

Para crear un mtodo nuevo para un formulario

Agregue un procedimiento declarado como Public, como en el cdigo siguiente:

VB C# C++ F# JScript

Copiar ' Create a custom method on a form. Public Sub PrintMyJob() ' Insert the code for your method here. End Sub

Para agregar un campo nuevo a un formulario

Declare una variable pblica en el mdulo del formulario, como en el cdigo siguiente:

VB C# C++ F# JScript

Copiar Public IDNumber As Integer

Para tener acceso a mtodos de un formulario distinto


1. Cree una nueva instancia del formulario a cuyos mtodos desea obtener acceso. Cuando hace referencia a un nombre de formulario, en realidad, est haciendo referencia a la clase a la cual pertenece el formulario, no propiamente al objeto.

Nota:
Visual Basic proporciona el mismo nombre a una variable global implcita que el formulario para cada clase de formulario. Para obtener ms informacin, consulte Cmo: Obtener acceso a un formulario.

2.

Asigne el formulario a una variable de objeto. La variable de objeto hace referencia a una instancia nueva de la clase de formulario. El ejemplo siguiente llama correctamente al procedimiento PrintMyJob:

VB C# C++ F# JScript

Copiar Dim newForm1 As New Form1 newForm1.PrintMyJob()

En el ejemplo anterior, no se muestra el formulario nuevo. No es necesario mostrar un objeto de formulario para utilizar sus mtodos. Para mostrar el formulario nuevo, debe agregar el cdigo siguiente:

VB C# C++ F# JScript

Copiar newForm1.Show()

Cmo: Obtener acceso a un formulario


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Puede tener acceso a los miembros de un formulario de Visual Basic sin tener que crear una variable. Los ejemplos siguientes muestran esto cambiando los colores en un formulario.

Tener acceso a un formulario

Para tener acceso a Form1


1. 2. 3. Asegrese de que su proyecto tiene una referencia al espacio de nombres System.Drawing. Esto es necesario para trabajar con la configuracin de colores, no para tener acceso al formulario. Cambie los colores directamente en Form1. Llame directamente al mtodo Show en Form1.

VB C# C++ F# JScript

Copiar Public Sub ChangeForm1Colors() Form1.ForeColor = System.Drawing.Color.Coral Form1.BackColor = System.Drawing.Color.Cyan Form1.Show() End Sub

Si Form1 no existe, Visual Basic lo crear. No tiene que declarar una variable para l.

Crear una instancia adicional de un formulario

Si desea crear un nuevo formulario, en lugar de tener acceso a uno existente, puede declarar una variable e inicializarla utilizando la palabra clave New.

Para crear una copia adicional de Form1


1. 2. Asegrese de que su proyecto tiene una referencia al espacio de nombres System.Drawing. Esto es necesario para trabajar con la configuracin de colores, no para tener acceso al formulario. Asigne New Form1 a una variable.

VB C# C++ F# JScript

Copiar Public Sub GetSecondInstance() Dim newForm1 As New Form1 newForm1.BackColor = System.Drawing.Color.YellowGreen newForm1.Show() End Sub

Si desea mostrar dos o ms copias del mismo formulario, debe crear copias adicionales. El ejemplo anterior crea una segunda copia de Form1 y lo pinta de un color diferente. Puede tener acceso a la copia original utilizando Form1 y a la segunda copia mediante newForm1.

Cmo: Obtener acceso a un formulario


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Puede tener acceso a los miembros de un formulario de Visual Basic sin tener que crear una variable. Los ejemplos siguientes muestran esto cambiando los colores en un formulario.

Tener acceso a un formulario

Para tener acceso a Form1


1. 2. 3. Asegrese de que su proyecto tiene una referencia al espacio de nombres System.Drawing. Esto es necesario para trabajar con la configuracin de colores, no para tener acceso al formulario. Cambie los colores directamente en Form1. Llame directamente al mtodo Show en Form1.

VB C#

C++ F# JScript

Copiar Public Sub ChangeForm1Colors() Form1.ForeColor = System.Drawing.Color.Coral Form1.BackColor = System.Drawing.Color.Cyan Form1.Show() End Sub

Si Form1 no existe, Visual Basic lo crear. No tiene que declarar una variable para l.

Crear una instancia adicional de un formulario

Si desea crear un nuevo formulario, en lugar de tener acceso a uno existente, puede declarar una variable e inicializarla utilizando la palabra clave New.

Para crear una copia adicional de Form1


1. 2. Asegrese de que su proyecto tiene una referencia al espacio de nombres System.Drawing. Esto es necesario para trabajar con la configuracin de colores, no para tener acceso al formulario. Asigne New Form1 a una variable.

VB C# C++ F# JScript

Copiar Public Sub GetSecondInstance() Dim newForm1 As New Form1 newForm1.BackColor = System.Drawing.Color.YellowGreen newForm1.Show() End Sub

Si desea mostrar dos o ms copias del mismo formulario, debe crear copias adicionales. El ejemplo anterior crea una segunda copia de Form1 y lo pinta de un color diferente. Puede tener acceso a la copia original utilizando Form1 y a la segunda copia mediante newForm1.

Cmo: Utilizar la nueva palabra clave


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Para crear una instancia de una clase, utilice la palabra clave New. A diferencia de los tipos de valor, como Integer y Double, los objetos son tipos de referencia, y debe crearlos de forma explcita antes de poder utilizarlos. Por ejemplo, observe las siguientes dos lneas de cdigo:

VB C# C++ F# JScript

Copiar Dim Button1 As System.Windows.Forms.Button Dim Button2 As New System.Windows.Forms.Button()

La primera instruccin declara una variable de objeto que puede contener una referencia a un objeto de botn. Sin embargo, la variable Button1 contiene el valor Nothing hasta que le asigne un objeto de tipo Button. La segunda instruccin tambin define una variable que puede contener un objeto de botn, pero la palabra clave New crea un objeto de botn y lo asigna a la variable Button2. Como los formularios y controles son en realidad clases, puede utilizar la palabra clave New para crear instancias nuevas de estos elementos, cuando sea necesario.

Para crear instancias nuevas de una clase con New


1. Abra un nuevo proyecto de aplicacin para Windows, y coloque un botn de comando y otros controles diversos en un formulario denominado Form1.

2.

Agregue el cdigo siguiente al procedimiento de evento Click del botn de comando:

VB C# C++ F# JScript

Copiar Dim f As New Form1 f.Show()

3. 4.

Ejecute la aplicacin, y haga clic en el botn de comando varias veces. Coloque a un lado el formulario frontal. Como el formulario es una clase con una interfaz visible, puede ver las copias adicionales. Cada copia tiene los mismos controles, en la misma posicin que los del formulario original en tiempo de diseo.

Puede utilizar la palabra clave New para crear objetos desde dentro de las clases. El procedimiento siguiente proporciona un ejemplo.

Para ver cmo New crea instancias de una clase


1. 2. 3. Abra un proyecto nuevo, y coloque un botn de comando en un formulario denominado Form1. En el men Proyecto, elija Agregar clase para agregar una clase al proyecto. Ponga a la clase nueva el nombre de ShowMe.vb.

4.

Agregue el procedimiento siguiente a ShowMe:

VB C# C++ F# JScript

Copiar Public Class ShowMe Sub ShowFrm() Dim frmNew As Form1 frmNew = New Form1 frmNew.Show() frmNew.WindowState = FormWindowState.Minimized End Sub End Class

5.

Agregue el cdigo siguiente para controlar el evento Click de Button1 de su formulario:

VB C# C++ F# JScript

Copiar Protected Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim clsNew As New ShowMe clsNew.ShowFrm() End Sub

6.

Para utilizar este ejemplo, ejecute la aplicacin y haga clic en el botn de comando varias veces. Aparecer un icono minimizado de formulario en la barra de tareas cada vez que se cree una instancia nueva de la clase ShowMe.

Administracin de recursos
Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Todos los objetos consumen recursos del sistema, como memoria, identificadores de archivo y conexiones de bases de datos. Common Language Runtime (CLR) administra los recursos automticamente y generalmente no hay que preocuparse de liberar los objetos innecesarios. No obstante, comprender cmo funciona la administracin de recursos puede ayudarle a disear las aplicaciones ms eficazmente.

Recoleccin de elementos no utilizados

CLR utiliza un sistema denominado recoleccin de elementos no utilizados para administrar los recursos asignados. La recoleccin de elementos no utilizados del sistema libera los recursos de un objeto cuando la ejecucin de cdigo de la aplicacin ya no puede tener acceso al objeto. El algoritmo de la recoleccin de elementos no utilizados es no determinista, por lo que no se puede determinar cundo los CLR liberarn los recursos de un objeto. En las siguientes secciones se describen algunos de los cambios en la forma de administrar los recursos en Visual Basic.

Asignar objetos a Nothing


Nothing es una palabra clave utilizada por Visual Basic para indicar que una variable de objeto no contiene una referencia a un objeto. En las versiones anteriores de Visual Basic se recomendaba asignar los objetos no utilizados a Nothing para disociar la variable de objeto y liberar recursos. An pueden asignarse objetos no utilizados a Nothing, pero debido a la forma en que Visual Basic administra los recursos, este proceso no garantiza que los objetos queden liberados inmediatamente. En general, slo se deben asignar a Nothing objetos duraderos (como miembros compartidos o variables globales).

Desechar
Algunos objetos admiten un mtodo denominado Dispose cuya finalidad consiste en liberar recursos del sistema de forma ms expeditiva. Las clases que admiten el mtodo Dispose deben implementar la interfaz IDisposable. Es necesario llamar explcitamente al mtodo Dispose cuando se deseen liberar recursos de objetos. Por ejemplo: ThisObject.Dispose()

Finalize
Otro mtodo que admiten algunas clases, Finalize, se ejecuta automticamente cuando se libera un objeto y puede utilizarse para realizar otras tareas de limpieza. El mtodo Finalize es similar al mtodo Class_Terminate() utilizado en versiones anteriores de Visual Basic. Despus de que un objeto quede

inaccesible, CLR llamar en el futuro al mtodo Finalize del objeto. Dado que el algoritmo de la recoleccin de elementos no utilizados es no determinista, se podra llamar al mtodo Finalize inmediatamente o despus varias horas.

Cmo: Pasar objetos a procedimientos


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Visual Basic permite pasar objetos como argumentos a procedimientos del mismo modo en que se pasan otros tipos de argumentos. Los procedimientos siguientes le mostrarn cmo hacerlo.

Para pasar una instancia nueva de un formulario a un procedimiento


1. 2. Abra un proyecto, cree un formulario nuevo llamado Form1 y agrguele un botn de comando denominado Button1. Copie el cdigo siguiente en el formulario:

VB C# C++ F# JScript

Copiar

Private Sub Button1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Button1.Click

Dim newForm As New Form1 newForm.Show() CenterForm(newForm) End Sub

Sub CenterForm(ByVal TheForm As Form) ' Centers the form on the screen. Dim RecForm As Rectangle = Screen.GetBounds(TheForm) TheForm.Left = CInt((RecForm.Width - TheForm.Width) / 2) TheForm.Top = CInt((RecForm.Height - TheForm.Height) / 2) End Sub

Tambin puede pasar un objeto como un argumento por referencia y posteriormente, en el procedimiento, establecer el argumento a un objeto nuevo.

Para pasar una referencia de objeto a un procedimiento de otro formulario


1. 2. 3. 4. 5. Abra un proyecto y cree un formulario denominado Form1. Agregue un segundo formulario denominado Form2. Coloque un control de cuadro de imagen en cada formulario. Ponga al cuadro de imagen de Form1 el nombre de PictureBox1. Ponga al cuadro de imagen de Form2 el nombre de PictureBox2.

6.

7.

Asigne una imagen a PictureBox2 haciendo clic en la propiedad Image de la ventana Propiedades. Funcionar cualquier imagen pequea; encontrar archivos .bmp y .jpg en el directorio de Windows. Agregue el cdigo siguiente a Form2:

VB C# C++ F# JScript

Copiar Public Sub GetPicture(ByVal x As PictureBox) Dim objX As PictureBox ' Assign the passed-in picture box to an object variable. objX = x ' Assign the value of the Picture property to the Form1 picture box. objX.Image = PictureBox2.Image End Sub

8.

Agregue el cdigo siguiente al evento Form1_Click de Form1:

VB C# C++ F# JScript

Copiar Protected Sub Form1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Dim newForm2 As New Form2 newForm2.GetPicture(PictureBox1) End Sub

9.

Ejecute la aplicacin y haga clic en Form1. La imagen de Form2 aparece en el cuadro de imagen de Form1. El procedimiento de evento Form1_Click llama al procedimiento GetPicture de Form2 y le pasa el cuadro de imagen vaco. El procedimiento GetPicture de Form2 asigna la propiedad Image del cuadro de imagen de Form2 al cuadro de imagen vaco de Form1, y la imagen de Form2 se muestra en Form1.

Tutorial: Guardar un objeto en Visual Basic


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Aunque en tiempo de diseo se pueden establecer las propiedades de un objeto en valores predeterminados, cualquier valor introducido en tiempo de ejecucin se pierde cuando se destruye el objeto. Puede usar la serializacin en Visual Basic para guardar los datos de un objeto entre instancias, lo que permite almacenar valores y recuperarlos la prxima vez que se cree una instancia del objeto. Para almacenar datos simples, como un nombre o un nmero, puede usar el objeto My.Settings. Para obtener ms informacin, vea My.Settings (Objeto). En este tutorial, crear un objeto Loan simple y guardar sus datos en un archivo. Recuperar a continuacin los datos del archivo al volver a crear el objeto. Por ltimo, modificar el cdigo para almacenar el objeto con un formato SOAP.

Nota de seguridad:
En este ejemplo se crea un nuevo archivo, si el archivo no existe ya. Si una aplicacin debe crear un archivo, necesitar tener permisos Create en la carpeta correspondiente. Los permisos se establecen usando listas de control de acceso. Sin embargo, si el archivo ya existe, la aplicacin slo precisar el permiso de Write, un permiso menor. Por tanto, siempre que sea posible, resulta ms seguro crear el archivo durante la implementacin y conceder slo permisos Read a un nico archivo (en lugar de conceder permisos Create a una carpeta). Tambin es ms seguro escribir datos en carpetas de usuario que en la carpeta raz o en la carpeta Archivos de programa.

Nota de seguridad:
En este ejemplo se almacenan datos en un formato de archivo binario o SOAP. Estos formatos no se deben usar con datos confidenciales, como contraseas o informacin de la tarjeta de crdito.

Nota:

Los cuadros de dilogo y los comandos de men que se ven pueden diferir de los descritos en la Ayuda, dependiendo de los valores de configuracin o de edicin activos. Para cambiar su configuracin, haga clic en Importar y exportar configuraciones en el men Herramientas. Para obtener ms informacin, vea Valores de configuracin de Visual Studio.

Crear el objeto Loan

El primer paso consiste en crear una clase Loan y una aplicacin de prueba que utilice esta clase.

Para crear la clase Loan


1. 2. 3. Cree un nuevo proyecto Biblioteca de clases y denomnelo "LoanClass". Para obtener ms informacin, vea Cmo: Crear soluciones y proyectos. En el Editor de cdigo, cambie el nombre de la clase de "Class1" a "Loan". Agregue a la clase los miembros pblicos siguientes:

VB C# C++ F# JScript

Copiar Public LoanAmount As Double = 10000.0

Public InterestRate As Double = 7.5 Public Term As Integer = 36 Public Customer As String

Tambin tendr que crear una aplicacin simple que utilice la clase Loan.

Para crear una aplicacin de prueba


1. 2. 3. 4. 5. 6. 7. 8. 9. Para agregar un proyecto de aplicacin para Windows a la solucin, haga clic en el men Archivo, a continuacin en Agregar y, por ltimo, en Nuevo proyecto. En el cuadro de dilogo Agregar nuevo proyecto, escriba LoanApp como el nombre del proyecto y haga clic en Aceptar para cerrar el cuadro de dilogo. En el Explorador de soluciones, seleccione el proyecto LoanApp. En el men Proyecto, haga clic en Establecer como proyecto de inicio. En el men Proyecto, haga clic en Agregar referencia. En el cuadro de dilogo Agregar referencia, haga clic en la ficha Proyectos y seleccione el proyecto LoanClass. Haga clic en Aceptar para cerrar el cuadro de dilogo. En el diseador, agregue cuatro controles TextBox al formulario. En el Editor de cdigos, agregue el siguiente cdigo:

VB C# C++ F# JScript

Copiar Private TestLoan As New LoanClass.Loan Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles MyBase.Load TextBox1.Text = TestLoan.LoanAmount.ToString TextBox2.Text = TestLoan.InterestRate.ToString TextBox3.Text = TestLoan.Term.ToString TextBox4.Text = TestLoan.Customer End Sub

Llegado este punto, puede generar y ejecutar la aplicacin. Observe que los valores predeterminados de la clase Loan aparecen en los cuadros de texto. Pruebe a cambiar el valor del tipo de inters de 7,5 a 7,1 y, a continuacin, cierre la aplicacin y ejectela de nuevo; el valor vuelve a ser el predeterminado de 7,5. En el mundo real, los tipos de inters cambian peridicamente, pero no forzosamente cada vez que se ejecuta la aplicacin. En lugar de hacer que el usuario actualice el tipo de inters cada vez que se ejecute la aplicacin, sera mejor guardar el tipo de inters ms reciente entre las instancias de la aplicacin. En el paso siguiente, har exactamente eso agregando la serializacin a la clase Loan.

Usar serializacin para guardar el objeto

Para guardar los valores de la clase Loan, primero debe marcarse la clase con el atributo Serializable.

Para marcar una clase como serializable

Cambie la declaracin de la clase Loan del modo siguiente:

VB

C# C++ F# JScript

Copiar <Serializable()> Public Class Loan

El atributo Serializable indica al compilador que todo el contenido de la clase se puede guardar en un archivo. En este caso, es probable que slo desee guardar el miembro InterestRate, y no los miembros Customer, LoanAmount o Period. El atributo NonSerialized se puede utilizar para marcar miembros de clase que no deberan guardarse. Por razones de simplicidad, en este ejemplo se guarda todo excepto el miembro Customer.

Para evitar que un miembro se serialice

Cambie la declaracin del miembro Customer del modo siguiente:

VB C# C++ F#

JScript

Copiar <NonSerialized()> Public Customer As String

El paso siguiente es agregar el cdigo de serializacin a la aplicacin LoanApp. Para serializar la clase y escribirla en un archivo, utilizar los espacios de nombres System.IO y System.Xml.Serialization. Para no tener que escribir los nombres completos, puede usar la instruccin Imports.

Para agregar referencias a espacios de nombres

Agregue las siguientes instrucciones Imports al comienzo de la clase Form1:

VB C# C++ F# JScript

Copiar Imports System.IO Imports System.Runtime.Serialization.Formatters.Binary

En este caso, est usando un formateador para guardar el objeto en un formato binario. Ms adelante en este tutorial modificar el cdigo para guardar el objeto en un formato SOAP. El paso siguiente es agregar cdigo para deserializar el objeto del archivo cuando se cree.

Para deserializar un objeto


1. Agregue una constante a la clase para el nombre de archivo de datos serializados.

VB C# C++ F# JScript

Copiar Const FileName As String = "SavedLoan.bin"

2.

Modifique el cdigo del procedimiento de evento Form1_Load del modo siguiente:

VB C# C++ F# JScript

Copiar Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles MyBase.Load If File.Exists(FileName) Then Dim TestFileStream As Stream = File.OpenRead(FileName) Dim deserializer As New BinaryFormatter TestLoan = CType(deserializer.Deserialize(TestFileStream), LoanClass.Loan) TestFileStream.Close() End If TextBox1.Text = TestLoan.LoanAmount.ToString TextBox2.Text = TestLoan.InterestRate.ToString

TextBox3.Text = TestLoan.Term.ToString TextBox4.Text = TestLoan.Customer End Sub

Observe que primero tiene que comprobar que el archivo existe. Si es as, cree una clase Stream para leer el archivo binario y una clase BinaryFormatter para traducirlo. El mtodo CType se usa para convertir del tipo de la secuencia al tipo del objeto Loan. A continuacin, tiene que agregar cdigo para guardar los datos introducidos en los cuadros de texto de la clase Loan y, a continuacin, debe serializar la clase en un archivo.

Para guardar los datos y serializar la clase

Agregue el siguiente cdigo al procedimiento de evento Form1_Closing:

VB C# C++ F# JScript

Copiar Private Sub Form1_Closing(ByVal sender As System.Object, ByVal e As _ System.ComponentModel.CancelEventArgs) Handles MyBase.Closing

TestLoan.LoanAmount = CType(TextBox1.Text, Double) TestLoan.InterestRate = CType(TextBox2.Text, Double) TestLoan.Term = CType(TextBox3.Text, Integer) TestLoan.Customer = TextBox4.Text

Dim TestFileStream As Stream = File.Create(FileName) Dim serializer As New BinaryFormatter serializer.Serialize(TestFileStream, TestLoan) TestFileStream.Close() End Sub

Llegado este punto, puede volver a generar y ejecutar la aplicacin. Inicialmente, los valores predeterminados aparecen en los cuadros de texto. Pruebe a cambiar los valores e introducir un nombre en el cuarto cuadro de texto. Cierre la aplicacin y, a continuacin, ejectela de nuevo. Observe que los valores nuevos aparecen ahora en los cuadros de texto, excepto el nombre del cliente que se marc como NonSerialized.

Guardar el objeto con un formato SOAP

En este ejemplo se ha mostrado hasta ahora cmo guardar un objeto en un archivo de texto usando un formato binario, que resulta correcto para la mayora de las aplicaciones Windows; sin embargo, para las aplicaciones web o los servicios web XML, es conveniente guardar el objeto en un archivo XML mediante un formato SOAP, que facilita compartir el objeto. Para guardar el objeto en un formato SOAP, primero debe hacerse referencia a la clase SoapFormatter. La clase SoapFormatter reside en su propio espacio de nombres: System.Runtime.Serialization.Formatters.Soap.

Para guardar el objeto con un formato SOAP


1. 2. 3. 4. 5. En el Explorador de soluciones, seleccione el proyecto LoanApp. En el men Proyecto, haga clic en Agregar referencia. En el cuadro de dilogo Agregar referencia, haga clic en la ficha .NET y seleccione el componente System.Runtime.Serialization.Formatters.Soap. Haga clic en Aceptar para cerrar el cuadro de dilogo. En el Editor de cdigo, agregue una instruccin Imports al comienzo del mdulo Form1:

VB C# C++ F# JScript

Copiar Imports System.Runtime.Serialization.Formatters.Soap

6. 7.

Cambie el nombre de archivo de SavedLoan.bin a SavedLoan.xml. En el procedimiento de evento Form1_Load, cambie la instruccin Dim de Dim deserializer As New BinaryFormatter a:

VB C# C++

F# JScript

Copiar Dim deserializer As New SoapFormatter

8.

En el procedimiento de evento Form1_Closing, cambie la instruccin Dim de Dim serializer As New BinaryFormatter a:

VB C# C++ F# JScript

Copiar Dim serializer As New SoapFormatter

Llegado este punto, puede generar y probar la aplicacin. La primera vez que ejecute la aplicacin, se crear el archivo SavedLoan.xml. Para ver el archivo, elija la opcin Mostrar todos los archivos en el Explorador de soluciones; se encuentra en el nodo Bin del proyecto de aplicacin para Windows.

Nota:
Si ya se encuentra en el modo Mostrar todos los archivos, para ver el archivo tendr que actualizar la vista; para ello, seleccione Actualizar en el men Ver.

Observe que los tres miembros de la clase LoanClass se muestran en formato XML. Cambie el valor de InterestRate en el archivo XML, a continuacin gurdelo y ejecute la aplicacin de nuevo. El nuevo tipo de inters aparecer en el segundo cuadro de texto.

Cmo: Heredar de una clase en Visual Basic


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Este ejemplo define las clases Circle y Rectangle que los dos heredan de la clase Shape y la clase Square que hereda de la clase Rectangle.

Ejemplo

Este ejemplo de cdigo tambin est disponible en el fragmento de cdigo de IntelliSense. En el selector de fragmentos de cdigo, se encuentra en Lenguaje Visual Basic. Para obtener ms informacin, vea Cmo: Insertar fragmentos de cdigo en el cdigo (Visual Basic).

VB C# C++ F# JScript

Copiar Public Class Shape ' Definitions of properties, methods, fields, and events. End Class Public Class Circle : Inherits Shape ' Specialized properties, methods, fields, events for Circle. End Class Public Class Rectangle : Inherits Shape ' Specialized properties, methods, fields, events for Rectangle. End Class Public Class Square : Inherits Rectangle ' Specialized properties, methods, fields, events for Square. End Class

Compilar el cdigo

Este ejemplo necesita:

Una referencia al espacio de nombres System.

Nota:
Asegrese de que la clase desde la que desea heredar no est definida como NotInheritable.

Cmo: Crear un objeto


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Una objeto es una instancia de una clase. Para usar los miembros de la clase debe crear primero un objeto a partir de ella.

Para crear un objeto a partir de una clase


1. 2. Determine en qu clase desea crear un objeto. Escriba Instruccin Dim (Visual Basic) para crear una variable a la que puede asignar una instancia de clase. La variable debe ser del tipo de la clase deseada.

Copiar Dim nextCustomer As customer


3. Agregue la palabra clave New (Visual Basic) para inicializar la variable a una nueva instancia de la clase.

Copiar

Dim nextCustomer As New customer


4. Puede tener acceso a los miembros de la clase ahora a travs de la variable de objeto.

Copiar nextCustomer.accountNumber = lastAccountNumber + 1

Programacin eficaz

Siempre que sea posible, debe declarar la variable para que sea del tipo de clase que piensa asignarle. Esto se llama enlace en tiempo de compilacin. Si no conoce el tipo de clase en el tiempo de compilacin, puede invocar el enlace en tiempo de ejecucin declarando la variable para que sea Object (Tipo de datos). Sin embargo, el enlace en tiempo de ejecucin puede ralentizar el rendimiento y limitar el acceso a los miembros del objeto en tiempo de ejecucin. Para obtener ms informacin, consulte Declaracin de variables de objeto.

Colecciones en Visual Basic


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 En trminos generales, una coleccin es un objeto utilizado para agrupar y administrar objetos relacionados. Por ejemplo, cada formulario Form tiene una coleccin de controles. (Puede tener acceso a esta coleccin a travs de la propiedad Controls del formulario.) Esta coleccin es un objeto que representa todos los controles de ese formulario. Le permite recuperar un control de la coleccin utilizando su ndice y recorrer en iteracin los elementos de la coleccin utilizando una Instruccin For Each...Next (Visual Basic). Sin embargo, hay varios tipos de colecciones y se diferencian entre s de varias maneras.

Diferentes tipos de colecciones

Visual Basic tambin proporciona una clase Collection, con la que puede definir y crear sus propias colecciones. Al igual que la coleccin Controls de un formulario, la clase Collection tambin proporciona la funcionalidad integrada que permite recorrer en iteracin los miembros mediante For Each...Next y recuperar los elementos usando su ndice. Para obtener ms informacin, vea Collection (Objeto, Visual Basic). Sin embargo, los dos tipos de colecciones no interoperan entre s. Por ejemplo, el cdigo siguiente genera un error del compilador: Dim localControls As Collection ' The following line generates a COMPILER ERROR. localControls = Me.Controls() Las colecciones son incompatibles porque la coleccin Controls es una coleccin de .NET Framework, mientras que la variable localControls es una Collection de Visual Basic. Los dos tipos de colecciones se implementan a partir de distintas clases. Sus mtodos son similares pero no idnticos y sus esquemas de indizacin son diferentes.

Colecciones basadas en cero y en uno

Una coleccin puede ser basada en cero o basada en uno, segn cul sea su ndice de comienzo. La primera de ellas significa que el ndice del primer elemento de la coleccin es 0, y la ltima, que es 1. Un ejemplo de coleccin basada en cero es la coleccin Controls de .NET Framework, explicada anteriormente en esta pgina. El objeto Collection de Visual Basic es un ejemplo de una coleccin basada en uno. Las colecciones basadas en uno pueden resultar ms intuitivas para los usuarios de Visual Basic, porque el intervalo del ndice se extiende desde 1 hasta el valor de Count (Propiedad, objeto Collection), que devuelve el nmero de elementos existentes en una coleccin. En cambio, el ndice de una coleccin basada en cero vara desde cero hasta el valor de la propiedad Count menos uno. Esto puede ser adecuado cuando los valores de ndice son desplazamientos respecto a un valor base o corresponder a miembros de una enumeracin basada en cero. Las colecciones de .NET Framework estn basadas en cero con el fin de seguir un esquema estndar. La clase Collection de Visual Basic est basada en uno con el fin de proporcionar compatibilidad con versiones anteriores.

Valores de ndice y de clave

Las instancias de la clase Collection de Visual Basic permiten tener acceso a un elemento utilizando un ndice numrico o una clave String. Puede agregar elementos a los objetos Collection de Visual Basic

especificando una clave o sin especificarla. Si agrega un elemento sin una clave, debe utilizar su ndice numrico para tener acceso a l. Por contraste, las colecciones como System.Collections.ArrayList slo permiten un ndice numrico. No se pueden asociar claves con los elementos de estas colecciones, a menos que construya las suyas propias basadas en asignaciones, por ejemplo, en una matriz de String que contiene las claves.

Agregar y quitar elementos

Las colecciones se diferencian en si se les puede o no agregar elementos y, en caso afirmativo, en cmo se pueden agregar. Puesto que el objeto Collection de Visual Basic es una herramienta de programacin de uso general, es ms flexible que algunas otras colecciones. Tiene un Add (Mtodo, objeto Collection) para colocar elementos en la coleccin y un Remove (Mtodo, objeto Collection) para quitar elementos de ella. Por otra parte, ciertas colecciones especializadas no permiten agregar o quitar elementos mediante cdigo. Por ejemplo, la propiedad CheckedListBox.CheckedItems devuelve una coleccin de referencias a elementos por ndice, pero su cdigo no puede agregar elementos a la coleccin ni quitarlos de ella. Slo el usuario puede hacer esta operacin, activando o desactivando la casilla de verificacin correspondiente en la interfaz de usuario. Por tanto, no hay ningn mtodo Add ni Remove para esta coleccin.

Eventos y controladores de eventos


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 A pesar de que puede visualizar un proyecto de Visual Studio como una serie de procedimientos que se ejecutan consecutivamente, en realidad la mayora de los programas estn dirigidos por eventos, es decir, el flujo de ejecucin est determinado por elementos externos denominados eventos. Un evento es una seal que comunica a una aplicacin que ha sucedido algo importante. Por ejemplo, cuando un usuario hace clic en un control de un formulario, el formulario puede provocar un evento Click y llamar a un procedimiento que controla el evento. Los eventos tambin permiten que las tareas separadas se comuniquen. Suponga, por ejemplo, que una aplicacin realiza una tarea de ordenacin

independientemente de la aplicacin principal. Si un usuario cancela la ordenacin, la aplicacin puede enviar un evento de cancelacin que ordene la detencin del proceso de ordenacin.

Conceptos y trminos de los eventos

Esta seccin describe los trminos y conceptos que se utilizan con eventos en Visual Basic.

Declarar eventos
Los eventos se declaran en clases, estructuras, mdulos e interfaces mediante la palabra clave Event, como se muestra en el siguiente ejemplo:

VB C# C++ F# JScript

Copiar Event AnEvent(ByVal EventNumber As Integer)

Producir eventos
Un evento es como un mensaje que anuncia que ha pasado algo importante. A la accin de difundir el mensaje se le llama producir el evento. En Visual Basic, los eventos se producen con la instruccin RaiseEvent, como en el ejemplo siguiente:

VB C# C++ F# JScript

Copiar RaiseEvent AnEvent(EventNumber)

Los eventos se deben provocar dentro del mbito de la clase, mdulo o estructura donde se declaran. Por ejemplo, una clase derivada no puede producir eventos heredados de una clase base.

Remitentes de eventos
Cualquier objeto capaz de producir un evento es un remitente de eventos, y tambin recibe el nombre de origen de eventos. Los formularios, controles y objetos definidos por el usuario son ejemplos de remitentes de eventos.

Controladores de eventos
Los controladores de eventos son procedimientos llamados cuando se produce un evento correspondiente. Puede utilizar cualquier subrutina vlida con una firma coincidente como controlador de eventos. No obstante, no puede utilizar una funcin como controlador de eventos, porque no puede devolver un valor al origen del evento. Visual Basic utiliza una convencin de nomenclatura estndar para controladores de eventos que combina el nombre del remitente del evento, un signo de subrayado y el nombre del evento. Por ejemplo, el evento Click de un botn denominado button1 recibira el nombre de Sub button1_Click.

Nota:
Es recomendable utilizar esta convencin de nomenclatura al definir controladores de eventos para sus propios eventos, pero no es estrictamente necesario; puede utilizar cualquier nombre de subrutina vlido.

Asociar eventos a controladores de eventos


Para que un controlador de eventos se pueda utilizar, primero debe asociarse a un evento mediante la instruccin Handles o AddHandler. La instruccin WithEvents y la clusula Handles proporcionan una forma declarativa de especificar controladores de eventos. Los eventos provocados por un objeto declarado con WithEvents los puede controlar cualquier subrutina con una clusula Handles que d nombre a este evento. Aunque la clusula Handles es la forma estndar de asociar un evento a un controlador de eventos, est limitada a asociar eventos a controladores de eventos en tiempo de compilacin. Las instrucciones AddHandler y RemoveHandler son ms flexibles que la clusula Handles. Le permiten conectar y desconectar de forma dinmica los eventos con uno o varios controladores de eventos en tiempo de ejecucin, y no requieren que declare variables de objeto mediante WithEvents. Sin embargo, hay algunas restricciones en el uso de WithEvents. Para obtener ms informacin, vea WithEvents y la clusula Handles. En algunos casos, como con eventos asociados a formularios o controles, Visual Basic finaliza automticamente un controlador de eventos vaco y lo asocia con un evento. Por ejemplo, al hacer doble clic en un botn de comando en un formulario en modo de diseo, Visual Basic crea un controlador de eventos vaco y una variable WithEvents para el botn de comando, como en el cdigo siguiente:

VB C# C++ F# JScript

Copiar Friend WithEvents Button1 As System.Windows.Forms.Button Protected Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click End Sub

WithEvents y la clusula Handles


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 La instruccin WithEvents y la clusula Handles proporcionan una forma declarativa de especificar controladores de eventos. Los eventos provocados por un objeto declarado con la palabra clave WithEvents pueden controlarse mediante cualquier procedimiento con una instruccin Handles para ese evento, tal y como se muestra en el ejemplo siguiente:

VB C#

C++ F# JScript

Copiar ' Declare a WithEvents variable. Dim WithEvents EClass As New EventClass

' Call the method that raises the object's events. Sub TestEvents() EClass.RaiseEvents() End Sub

' Declare an event handler that handles multiple events. Sub EClass_EventHandler() Handles EClass.XEvent, EClass.YEvent MsgBox("Received Event.") End Sub

Class EventClass Public Event XEvent() Public Event YEvent() ' RaiseEvents raises both events. Sub RaiseEvents() RaiseEvent XEvent() RaiseEvent YEvent()

End Sub End Class

La instruccin WithEvents y la clusula Handles son a menudo la mejor opcin para los controladores de eventos, ya que la sintaxis declarativa que utilizan hace que el control de eventos sea ms sencillo de codificar, leer y depurar. No obstante, tenga en cuenta las siguientes limitaciones en la utilizacin de las variables WithEvents:

No se puede utilizar una variable WithEvents como variable de objeto. Es decir, no es posible declararla como Object; se debe especificar el nombre de clase al declarar la variable. Dado que los eventos compartidos no estn asociados a instancias de clase, no se puede usar WithEvents para controlar los eventos mediante declaraciones compartidas. De forma parecida, no se puede utilizar WithEvents ni Handles para controlar los eventos desde una estructura Structure. En ambos casos, puede utilizar la instruccin AddHandler para controlar esos eventos. No se pueden crear matrices de variables WithEvents. Las variables WithEvents permiten que un solo controlador controle uno o ms tipos de eventos, as como que uno o ms controladores de eventos controlen el mismo tipo de evento.

AddHandler y RemoveHandler
Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 La instruccin AddHandler se parece a la clusula Handles en que las dos permiten especificar un controlador de eventos. Sin embargo, AddHandler, utilizado con RemoveHandler, proporciona ms flexibilidad que la clusula Handles, lo que permite agregar, quitar y cambiar de forma dinmica el controlador de errores asociado con un evento. Si desea controlar eventos compartidos o eventos de una estructura, debe utilizar AddHandler. AddHandler toma dos argumentos: el nombre de un evento de un remitente de evento, como un control, y una expresin que evala a un delegado. No necesita especificar explcitamente la clase delegada al utilizar AddHandler, ya que la instruccin AddressOf siempre devuelve una referencia al delegado. El ejemplo siguiente asocia un controlador de eventos a un evento provocado por un objeto:

VB C# C++ F# JScript

Copiar AddHandler Obj.XEvent, AddressOf Me.XEventHandler

RemoveHandler, que desconecta un evento de un controlador de eventos, utiliza la misma sintaxis que AddHandler. Por ejemplo:

VB C# C++ F# JScript

Copiar RemoveHandler Obj.XEvent, AddressOf Me.XEventHandler

Cmo: Agregar eventos a una clase


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Se agregan eventos a una clase declarndolos con la instruccin Events. La declaracin incluye el nombre del evento y los argumentos que utiliza. La accin de agregar un evento a una clase determina que un objeto de esta clase puede provocar un evento especfico. Para conseguir que se produzca un evento, se debe utilizar la instruccin RaiseEvent. Puede utilizar la palabra clave Handles o la instruccin AddHandler para asociar el evento a un procedimiento controlador de eventos. Los eventos deben producirse dentro del mbito en el que se han declarado. Por ejemplo, una clase derivada no puede producir eventos heredados de una clase base.

Nota:
Los eventos no pueden tener valores devueltos, argumentos opcionales o argumentos ParamArray.

Para agregar un evento a una clase

En la seccin Declaraciones del mdulo de clase que define la clase, utilice la instruccin Event para declarar el evento con cualquier argumento que desee que tenga. Por ejemplo:

VB C# C++ F# JScript

Copiar Public Event PercentDone(ByVal Percent As Single, _ ByRef Cancel As Boolean)

Cmo: Provocar un evento (Visual Basic)


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 En este ejemplo se define un evento (TimeExpired) y se utiliza la instruccin RaiseEvent para hacer que se produzca el evento.

Ejemplo

VB C# C++ F# JScript

Copiar Public Event TimeExpired(ByVal Status As String) Public Sub RaiseTimeExpiredEvent() RaiseEvent TimeExpired("Your time has run out") End Sub

Este ejemplo de cdigo tambin est disponible como fragmento de cdigo de IntelliSense. En el selector de fragmentos de cdigo, se encuentra en Lenguaje Visual Basic. Para obtener ms informacin, vea Cmo: Insertar fragmentos de cdigo en el cdigo (Visual Basic).

Compilar el cdigo

Para este ejemplo se necesita:

Acceso a los miembros del espacio de nombres System. Agregue una instruccin Imports si no incluye nombres de miembro completos en el cdigo. Para obtener ms informacin, vea Instruccin Imports (Tipo y espacio de nombres de .NET). La instruccin Event debe estar en el nivel de la clase, no dentro de ningn procedimiento. La instruccin RaiseEvent debe estar dentro de algn procedimiento de la aplicacin.

Cmo: Crear un evento y un controlador (Visual Basic)


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 En este ejemplo se define un evento, TimeExpired, y un controlador de eventos, HandleTimeExpired, y se utiliza la instruccin AddHandler para asociarlos.

Ejemplo

VB C# C++ F#

JScript

Copiar Public Event TimeExpired(ByVal Status As String) Public Sub HandleTimeExpired(ByVal Status As String) ' Perform desired processing for when time has expired. MsgBox("HandleTimeExpired caught the TimeExpired event" & _ vbCrLf & "Status = " & Status) End Sub Public Sub SetUpEventHandler() AddHandler TimeExpired, AddressOf HandleTimeExpired End Sub

Compilar el cdigo

Para este ejemplo se necesita:

Acceso a los miembros del espacio de nombres System. Agregue una instruccin Imports si no incluye nombres de miembro completos en el cdigo. Para obtener ms informacin, vea Instruccin Imports (Tipo y espacio de nombres de .NET). La instruccin Event debe estar en el nivel de la clase, no dentro de ningn procedimiento. La instruccin Event y ambos procedimientos (HandleTimeExpired y SetUpEventHandler) deben estar definidos en la misma clase o el mismo mdulo. De lo contrario, la instruccin AddHandler debe calificar el evento y el controlador para los objetos en los que estn definidos.

Cmo: Escribir controladores de eventos


Visual Studio 2008

Otras versiones

Actualizacin: noviembre 2007 La forma de crear un controlador de eventos depende de cmo quiera asociarlo a los eventos. La manera estndar de crear un controlador de eventos consiste en usar la palabra clave Handles con la palabra clave WithEvents. Visual Basic proporciona una segunda forma de controlar los eventos: la instruccin AddHandler. AddHandler y RemoveHandler le permiten iniciar y detener dinmicamente el control de un evento especfico. Es posible utilizar ambos enfoques, pero no se debe utilizar WithEvents y AddHandler en el mismo evento.

Controlar eventos mediante WithEvents

La palabra clave WithEvents permite crear variables de objeto en el nivel de mdulo o clase que pueden utilizarse con la clusula Handles en controladores de eventos.

Para controlar eventos mediante WithEvents y la clusula Handles


1. Cree una clase simple que contiene un evento.

VB C# C++ F# JScript

Copiar Class Class1 Public Event AnEvent(ByVal EventNumber As Integer) End Class

2.

En la clase o el mdulo que controlar el evento, utilice la palabra clave WithEvents para declarar una variable de objeto para el cdigo fuente de los eventos, como en el ejemplo siguiente:

VB C# C++ F# JScript

Copiar Public WithEvents ClassInst As Class1

3. 4.

En el Editor de cdigo, elija la variable WithEvents que acaba de declarar en la lista desplegable Nombre de clase de la parte izquierda. Elija el evento que desea controlar de la lista desplegable Method Name en la parte derecha. El Editor de cdigo crea el procedimiento controlador de eventos vaco con una clusula Handles.

Nota:
Este paso es opcional. Puede crear el procedimiento controlador de eventos de forma manual mientras el procedimiento que se crea sea una subrutina, tenga la lista de argumentos correcta para que coincida con el evento que se controla y tenga una clusula Handles que especifique el evento que se controla.

5.

Agregue cdigo de control de eventos al procedimiento controlador de eventos utilizando los argumentos suministrados. El cdigo siguiente proporciona un ejemplo:

VB C# C++ F# JScript

Copiar Public Sub ClassInst_AnEvent(ByVal EventNumber As Integer) _

Handles ClassInst.AnEvent MsgBox("Received event number: " & CStr(EventNumber)) End Sub

Controlar eventos mediante AddHandler

Se puede utilizar la instruccin AddHandler para conectar de forma dinmica eventos a procedimientos controladores de eventos.

Para controlar eventos mediante AddHandler


1. Cree una subrutina para controlar el evento, como en el ejemplo siguiente:

VB C# C++ F# JScript

Copiar Public Sub EHandler(ByVal EventNumber As Integer)

MsgBox("Received event number " & CStr(EventNumber)) End Sub

2.

Declare una variable de objeto de la clase que sea el origen de los eventos y que desea controlar. A diferencia de la variable WithEvents, puede ser una variable local en un procedimiento. Por ejemplo:

VB C# C++ F# JScript

Copiar Public Sub TestAddHandler() Dim CI As New Class1 End Sub

3.

Utilice la instruccin AddHandler para especificar el nombre del remitente del evento, y la instruccin AddressOf para proporcionar el nombre del controlador de eventos. Por ejemplo, agregue el cdigo siguiente al final de la subrutina TestAddHandler:

VB C# C++ F# JScript

Copiar AddHandler CI.AnEvent, AddressOf EHandler

Cualquier procedimiento puede servir como controlador de eventos siempre que admita los argumentos correctos para el evento que se controla.

Utilizar RemoveHandler para detener el control de eventos

Puede utilizar la instruccin RemoveHandler para desconectar de forma dinmica eventos de procedimientos controladores de eventos.

+Para detener el control de eventos con RemoveHandler

Utilice la instruccin RemoveHandler para especificar el nombre del remitente del evento y la instruccin AddressOf para proporcionar el nombre del controlador de eventos. La sintaxis para las instrucciones RemoveHandler siempre coincidir exactamente con la instruccin AddHandler utilizada para iniciar el control de eventos. Por ejemplo:

VB C# C++ F# JScript

Copiar RemoveHandler CI.AnEvent, AddressOf EHandler

Controlar eventos heredados de una clase base

Las clases derivadas (clases que heredan caractersticas de una clase base) pueden controlar eventos provocados por su clase base mediante la instruccin HandlesMyBase.

Controlar eventos de una clase base

Declare un controlador de eventos en la clase derivada agregando una instruccin Handles MyBase.nombreDeEvento a la lnea de declaracin del procedimiento controlador de eventos,

donde nombreDeEvento es el nombre del evento de la clase base que est controlando. Por ejemplo:

VB C# C++ F# JScript

Copiar Public Class BaseClass Public Event BaseEvent(ByVal i As Integer) ' Place methods and properties here. End Class

Public Class DerivedClass Inherits BaseClass Sub EventHandler(ByVal x As Integer) Handles MyBase.BaseEvent ' Place code to handle events from BaseClass here. End Sub End Class

Cmo: Controlar eventos en Visual Basic


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 En el ejemplo siguiente se define una clase que produce un evento al llamar al mtodo CauseEvent. Este evento est controlado por un procedimiento controlador de eventos denominado EventHandler.

Ejemplo

Descripcin
Para ejecutar este ejemplo, agregue el cdigo siguiente a la clase de formulario de un proyecto de aplicacin para Windows Visual Basic y llame al procedimiento TestEvents con un argumento de tipo integer.

Cdigo

VB C# C++ F#

JScript

Copiar Public Class Class1 ' Declare an event for this class. Public Event Event1(ByVal EventNumber As Integer) ' Define a method that raises an event. Sub CauseEvent(ByVal EventNumber As Integer) RaiseEvent Event1(EventNumber) End Sub End Class

Protected Sub TestEvents(ByVal EventNumber As Integer) Dim Obj As New Class1 AddHandler Obj.Event1, AddressOf Me.EventHandler ' Cause the object to raise an event. Obj.CauseEvent(EventNumber) End Sub

Sub EventHandler(ByVal EventNumber As Integer) MsgBox("Received event number " & EventNumber.ToString) End Sub

Tutorial: Declarar y provocar eventos


Visual Studio 2008

Otras versiones

Actualizacin: noviembre 2007 Este tutorial explica cmo declarar y provocar eventos para una clase denominada Widget. Cuando finalice los pasos tal vez desee leer el tema complementario, Tutorial: Controlar eventos, que muestra cmo utilizar eventos de objetos Widget para proporcionar informacin de estado en una aplicacin.

La clase Widget

Suponga por el momento que tiene una clase Widget. Su clase Widget tiene un mtodo que puede tardar bastante tiempo en ejecutarse, y desea que la aplicacin pueda establecer alguna clase de indicador de finalizacin. Por supuesto, podra hacer que el objeto Widget mostrara un cuadro de dilogo de porcentaje finalizado, pero entonces ese cuadro de dilogo aparecera en cada proyecto en el que utilizase la clase Widget. Un buen principio del diseo de objetos consiste en dejar que la aplicacin que utiliza un objeto controle la interfaz de usuario, a no ser que el objeto tenga como nica finalidad administrar un formulario o un cuadro de dilogo. La finalidad de Widget es realizar otras tareas, de modo que es mejor agregar un evento PercentDone y dejar que el procedimiento que llama a los mtodos de Widget lo controle y muestre las actualizaciones del estado. El evento PercentDone tambin puede proporcionar un mecanismo para cancelar la tarea.

Para generar el ejemplo de cdigo para este tema


1. 2. 3. Abra un nuevo proyecto de aplicacin para Windows de Visual Basic y cree un formulario llamado Form1. Agregue dos botones y una etiqueta a Form1. D nombre a los objetos como se muestra en la tabla siguiente.

Objeto
Button1 Button2 Label

Propiedad
Text Text (Name), Text

Ajuste
Start Task Cancelar lblPercentDone, 0

4.

En el men Proyecto, elija Agregar clase para agregar al proyecto una clase denominada Widget.vb.

Para declarar un evento para la clase Widget

Utilice la palabra clave Event para declarar un evento en la clase Widget. Observe que un evento puede tener argumentos ByVal y ByRef, como se puede ver en el evento PercentDone de Widget:

VB C# C++ F# JScript

Copiar Public Event PercentDone(ByVal Percent As Single, _ ByRef Cancel As Boolean)

Cuando el objeto de llamada recibe un evento PercentDone, el argumento Percent contiene el porcentaje de la tarea que se ha finalizado. El argumento Cancel se puede establecer en True para cancelar el mtodo que provoc el evento.

Nota:

Los argumentos de eventos se pueden declarar igual que se hace con los argumentos de procedimientos, con las siguientes excepciones: los eventos no pueden tener argumentos Optional, ParamArray, ni valores devueltos.

El evento PercentDone lo produce el mtodo LongTask de la clase Widget. LongTask acepta dos argumentos: el perodo de tiempo durante el cual el mtodo simular trabajar y el intervalo de tiempo mnimo antes de que LongTask se detenga para provocar el evento PercentDone.

Para provocar el evento PercentDone


1. Para simplificar el acceso a la propiedad Timer utilizada por esta clase, agregue una instruccin Imports a la parte superior de la seccin de declaraciones del mdulo de clase, por encima de la instruccin Class Widget.

VB C# C++ F# JScript

Copiar Imports Microsoft.VisualBasic.DateAndTime

2.

Agregue el cdigo siguiente a la clase Widget:

VB C# C++ F# JScript

Copiar Public Sub LongTask(ByVal Duration As Single, _ ByVal MinimumInterval As Single) Dim Threshold As Single Dim Start As Single Dim blnCancel As Boolean

' The Timer property of the DateAndTime object returns the seconds ' and milliseconds that have passed since midnight. Start = CSng(Timer) Threshold = MinimumInterval

Do While CSng(Timer) < (Start + Duration)

' In a real application, some unit of work would ' be done here each time through the loop. If CSng(Timer) > (Start + Threshold) Then RaiseEvent PercentDone( _ Threshold / Duration, blnCancel) ' Check to see if the operation was canceled. If blnCancel Then Exit Sub Threshold = Threshold + MinimumInterval End If Loop End Sub

Cuando su aplicacin llama al mtodo LongTask, la clase Widget provoca el evento PercentDone cada vez que transcurran los especificados en MinimumInterval. Cuando se vuelve del evento, LongTask comprueba si se estableci en True el argumento Cancel. En este punto son necesarias algunas aclaraciones. Para simplificar, en el procedimiento LongTask se supone que el usuario conoce de antemano cunto tarda en realizarse la tarea. Esto casi nunca es as. Dividir las tareas en bloques del mismo tamao puede resultar difcil y, a menudo, lo que es ms importante para los usuarios es simplemente el tiempo que transcurre antes de recibir una indicacin de que algo est ocurriendo. Tambin puede haber detectado otro error en este ejemplo. La propiedad Timer devuelve el nmero de segundos transcurridos desde medianoche; por lo tanto, la aplicacin se bloquea si se inicia inmediatamente antes de medianoche. Una forma ms cuidadosa de medir el tiempo tendra en cuenta condiciones de lmite como sta, o las evitara globalmente utilizando propiedades como Now. Ahora que la clase Widget puede provocar eventos, puede continuar con el siguiente tutorial. Tutorial: Controlar eventos explica cmo utilizar WithEvents para asociar un controlador de eventos con el evento PercentDone.

Tutorial: Controlar eventos


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 ste es el segundo de los dos temas que muestran cmo trabajar con eventos. En el primer tema, Tutorial: Declarar y provocar eventos, se muestra cmo declarar y provocar eventos. Esta seccin utiliza el formulario y la clase del tutorial para mostrar cmo controlar eventos cuando tienen lugar. La clase Widget de ejemplo utiliza las instrucciones de control de eventos tradicionales. Visual Basic proporciona otras tcnicas para trabajar con eventos. Como ejercicio, puede modificar este ejemplo para utilizar las instrucciones AddHandler y Handles.

Para controlar el evento PercentDone de la clase Widget

Coloque el cdigo siguiente en Form1:

VB C# C++ F# JScript

Copiar Private WithEvents mWidget As Widget

Private mblnCancel As Boolean

La palabra clave WithEvents especifica que se utiliza la variable mWidget para controlar los eventos de un objeto. Puede especificar el tipo de objeto proporcionando el nombre de la clase de la que se crear el objeto. La variable mWidget se declara en Form1 porque las variables WithEvents deben ser de nivel de clase. Esto es cierto independientemente del tipo de mdulo donde se coloquen. Se utiliza la variable mblnCancel para cancelar el mtodo LongTask.

Escritura de cdigo para controlar eventos

Tan pronto como declara una variable utilizando WithEvents, el nombre de variable aparece en la lista desplegable izquierda del Editor de cdigo de la clase. Cuando selecciona mWidget, aparecen los eventos de la clase Widget en la lista desplegable derecha. Al seleccionar un evento se muestra el procedimiento de evento correspondiente, con el prefijo mWidget y un carcter de subrayado. Se da a todos los procedimientos de eventos asociados a la variable WithEvents el nombre de variable como prefijo.

Para controlar un evento


1. 2. Seleccione mWidget en la lista desplegable izquierda del Editor de cdigo. Seleccione el evento PercentDone en la lista desplegable derecha. El Editor de cdigo abre el procedimiento de evento mWidget_PercentDone.

Nota:
El Editor de cdigo es til, pero no necesario, para insertar los nuevos controladores de eventos. En este tutorial, es ms directo copiar simplemente los controladores de eventos en el cdigo.

3.

Agregue el cdigo siguiente al controlador de eventos mWidget_PercentDone:

VB C# C++ F# JScript

Copiar Private Sub mWidget_PercentDone( _ ByVal Percent As Single, _ ByRef Cancel As Boolean _ ) Handles mWidget.PercentDone lblPercentDone.Text = CInt(100 * Percent) & "%" My.Application.DoEvents() If mblnCancel Then Cancel = True End Sub

Siempre que se provoca el evento PercentDone, el procedimiento de evento muestra el porcentaje completo en un control Label. El mtodo DoEvents permite volver a dibujar la etiqueta y tambin le da al usuario la oportunidad de hacer clic en el botn Cancel. 4. Agregue el cdigo siguiente para el controlador de eventos Button2_Click:

VB C# C++ F# JScript

Copiar Private Sub Button2_Click( _ ByVal sender As Object, _ ByVal e As System.EventArgs _ ) Handles Button2.Click mblnCancel = True End Sub

Si el usuario hace clic en el botn Cancel cuando se est ejecutando LongTask, se ejecuta el evento Button2_Click tan pronto como la instruccin DoEvents permite que se produzca el procesamiento de eventos. La variable mblnCancel de nivel de clase se establece como True y el evento mWidget_PercentDone lo comprueba luego y establece el argumento ByRef Cancel como True.

Conectar la variable WithEvents con un objeto

Form1 est ahora configurado para controlar los eventos de un objeto Widget. Slo queda buscar un objeto Widget en alguna parte.

Cuando declara una variable WithEvents en tiempo de diseo, no se asocia ningn objeto a sta. La variable WithEvents es como cualquier otra variable de objeto. Tendr que crear un objeto y asignar una referencia a ste con la variable WithEvents.

Para crear un objeto y asignarlo una referencia


1. 2. 3. Seleccione (Eventos Form1) en la lista desplegable izquierda del Editor de cdigo. Seleccione el evento Load en la lista desplegable derecha. El Editor de cdigo abre el procedimiento de evento Form1_Load. Agregue el cdigo siguiente para el procedimiento de evento Form1_Load a fin de crear el objeto Widget:

VB C# C++ F# JScript

Copiar Private Sub Form1_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs _ ) Handles MyBase.Load mWidget = New Widget End Sub

Cuando se ejecuta este cdigo, Visual Basic crea un objeto Widget y conecta sus eventos a los procedimientos de evento asociados con mWidget. Desde este momento en adelante, siempre que el objeto Widget provoque el evento PercentDone, se ejecutar el procedimiento de evento mWidget_PercentDone.

Para llamar al mtodo LongTask

Agregue el cdigo siguiente al controlador de eventos Button1_Click:

VB C# C++ F# JScript

Copiar Private Sub Button1_Click( _ ByVal sender As Object, _ ByVal e As System.EventArgs _ ) Handles Button1.Click mblnCancel = False lblPercentDone.Text = "0%"

lblPercentDone.Refresh() mWidget.LongTask(12.2, 0.33) If Not mblnCancel Then lblPercentDone.Text = CStr(100) & "%" End Sub

Antes de llamar al mtodo LongTask, la etiqueta que muestra el porcentaje completo debe inicializarse y el indicador Boolean de nivel de clase que cancela el mtodo debe establecerse como False. LongTask se llama con una duracin de tarea de 12,2 segundos. Se provoca el evento PercentDone una vez cada tercio de segundo. Cada vez que se provoca el evento, se ejecuta el procedimiento de evento mWidget_PercentDone. Cuando termina LongTask, se comprueba mblnCancel para ver si LongTask ha finalizado de forma normal o si se ha detenido porque mblnCancel estaba establecido como True. El porcentaje completo se actualiza slo en el primer caso.

Para ejecutar el programa


1. 2. 3. Presione F5 para poner el proyecto en modo de ejecucin. Haga clic en el botn Iniciar tarea. Cada vez que se provoca el evento PercentDone, se actualiza la etiqueta con el porcentaje de la tarea que se ha completado. Haga clic en el botn Cancelar para detener la tarea. Observe que la apariencia del botn Cancelar no cambia inmediatamente cuando se hace clic en l. El evento Click no puede tener lugar hasta que la instruccin My.Application.DoEvents permita el procesamiento del evento.

Nota:
El mtodo My.Application.DoEvents no procesa los eventos exactamente de la misma manera en que lo hace el formulario. Por ejemplo, en este tutorial, debe hacer clic dos veces en el botn Cancelar. Para permitir que el formulario controle directamente los eventos, puede utilizar el subprocesamiento mltiple. Para obtener ms informacin, vea Subprocesamiento mltiple en Visual Basic.

Puede resultarle instructivo ejecutar el programa con F11 y recorrer el cdigo lnea a lnea. Puede ver claramente cmo la ejecucin escribe LongTask y luego vuelve a escribir Form1 brevemente cada vez que se provoca el evento PercentDone. Qu sucedera si cuando se estaba devolviendo la ejecucin al cdigo de Form1, se llamara al mtodo LongTask de nuevo? En el peor de los casos, podra ocurrir un desbordamiento de la pila si se llamara a LongTask cada vez que se provocara el evento.

Puede hacer que la variable mWidget controle los eventos de un objeto Widget distinto asignando una referencia al nuevo Widget con mWidget. De hecho, puede hacer que el cdigo de Button1_Click realice esto cada vez que hace clic en el botn.

Para controlar eventos para un Widget distinto

Agregue la lnea de cdigo siguiente al procedimiento Button1_Click, inmediatamente antes de la lnea que indica mWidget.LongTask(12.2, 0.33):

VB C# C++ F# JScript

Copiar mWidget = New Widget ' Create a new Widget object.

El cdigo anterior crea un nuevo Widget cada vez que se hace clic en el botn. Tan pronto como finaliza el mtodo LongTask, se libera la referencia al objeto Widget y se destruye ste. Las variables WithEvents pueden contener slo una referencia a objeto a la vez, de modo que si asigna otro objeto Widget a mWidget, los eventos del objeto Widget anterior ya no se controlarn. Si mWidget es la nica variable de objeto que contiene una referencia al objeto Widget antiguo, ste se destruir. Si

desea controlar eventos desde varios objetos Widget, utilice la instruccin AddHandler para procesar independientemente los eventos de cada objeto.

Nota:
Puede declarar todas las variables WithEvents que sean necesarias, pero no se admiten las matrices de variables WithEvents.

Cmo: Declarar eventos que evitan bloqueos


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Hay varias circunstancias en las que resulta importante que un controlador de eventos no bloquee los controladores de eventos subsiguientes. Los eventos personalizados permiten al evento llamar de forma asincrnica a sus controladores de eventos. De manera predeterminada, el campo de almacn de respaldo de una declaracin de evento es un delegado multidifusin que combina de forma consecutiva todos los controladores de eventos. Esto significa que si un controlador tarda mucho tiempo en completarse, bloquea a los dems controladores hasta que finaliza. (Los controladores de eventos con buen comportamiento no deben realizar operaciones largas ni que puedan producir bloqueos.) En lugar de utilizar la implementacin predeterminada de eventos que proporciona Visual Basic, puede utilizar un evento personalizado para ejecutar los controladores de eventos de forma asincrnica.

Ejemplo

En este ejemplo, el descriptor de acceso AddHandler agrega el delegado para cada controlador del evento Click en un elemento ArrayList almacenado en el campo EventHandlerList. Cuando el cdigo provoca el evento Click, el descriptor de acceso RaiseEvent invoca a todos los delegados del controlador de eventos de forma asincrnica con el mtodo BeginInvoke. Ese mtodo

invoca cada controlador en un subproceso de trabajo y vuelve inmediatamente, por lo que los controladores no se pueden bloquear entre si.

VB C# C++ F# JScript

Copiar Public NotInheritable Class ReliabilityOptimizedControl 'Defines a list for storing the delegates Private EventHandlerList As New ArrayList

'Defines the Click event using the custom event syntax. 'The RaiseEvent always invokes the delegates asynchronously Public Custom Event Click As EventHandler AddHandler(ByVal value As EventHandler) EventHandlerList.Add(value) End AddHandler RemoveHandler(ByVal value As EventHandler) EventHandlerList.Remove(value) End RemoveHandler

RaiseEvent(ByVal sender As Object, ByVal e As EventArgs) For Each handler As EventHandler In EventHandlerList If handler IsNot Nothing Then handler.BeginInvoke(sender, e, Nothing, Nothing) End If Next End RaiseEvent End Event End Class

Cmo: Declarar eventos que evitan que se pierda memoria


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Hay varias circunstancias en las que es importante que una aplicacin mantenga un bajo uso de memoria. Los eventos personalizados permiten a la aplicacin utilizar memoria slo para los eventos que controla. De manera predeterminada, cuando una clase declara un evento, el compilador asigna memoria para que un campo almacene informacin de eventos. Si una clase tiene muchos eventos no usados, ocupan memoria intilmente. En lugar de utilizar la implementacin predeterminada de los eventos que Visual Basic proporciona, puede utilizar los eventos personalizados para administrar ms cuidadosamente el uso de memoria.

Ejemplo

En este ejemplo, la clase utiliza una instancia de la clase EventHandlerList, almacenada en el campo Events, para guardar informacin sobre los eventos que estn en uso. La clase EventHandlerList es una clase de lista optimizada diseada para contener delegados. Todos los eventos de la clase usan el campo Events para realizar un seguimiento de qu mtodos est controlando cada evento.

VB C# C++ F# JScript

Copiar Public Class MemoryOptimizedBaseControl ' Define a delegate store for all event handlers. Private Events As New System.ComponentModel.EventHandlerList

' Define the Click event to use the delegate store. Public Custom Event Click As EventHandler AddHandler(ByVal value As EventHandler) Events.AddHandler("ClickEvent", value) End AddHandler RemoveHandler(ByVal value As EventHandler)

Events.RemoveHandler("ClickEvent", value) End RemoveHandler RaiseEvent(ByVal sender As Object, ByVal e As EventArgs) CType(Events("ClickEvent"), EventHandler).Invoke(sender, e) End RaiseEvent End Event

' Define the Click event to use the same delegate store. Public Custom Event DoubleClick As EventHandler AddHandler(ByVal value As EventHandler) Events.AddHandler("DoubleClickEvent", value) End AddHandler RemoveHandler(ByVal value As EventHandler) Events.RemoveHandler("DoubleClickEvent", value) End RemoveHandler RaiseEvent(ByVal sender As Object, ByVal e As EventArgs) CType(Events("DoubleClickEvent"), EventHandler).Invoke(sender, e) End RaiseEvent End Event

' Define additional events to use the same delegate store. ' ... End Class

Solucionar problemas de controladores de eventos heredados en Visual Basic


Visual Studio 2008

Otras versiones

Actualizacin: noviembre 2007 Este tema enumera problemas comunes que surgen con controladores de eventos en componentes heredados.

Procedimientos

El cdigo de un controlador de eventos se ejecuta dos veces por llamada

Un controlador de eventos heredado no debe incluir una clusula Handles. El mtodo de la clase base est asociado ya con el evento y se iniciar en consecuencia. Quite la clusula Handles del mtodo heredado.

VB C# C++ F# JScript

Copiar

' INCORRECT Protected Overrides Sub Button1_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles Button1.Click

' The Handles clause will cause all code ' in this block to be executed twice. End Sub

Si el mtodo heredado no tiene una palabra clave Handles, compruebe que el cdigo no contiene una instruccin AddHandler (Instruccin) o mtodos adicionales que controlen el mismo evento.

Delegados de Visual Basic Los delegados y el operador AddressOf


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Los delegados son objetos que puede utilizar para llamar a los mtodos de otros objetos. Algunas veces estn descritos como punteros de funcin con seguridad de tipos porque son parecidos a los punteros de funcin utilizados en otros lenguajes de programacin. Sin embargo, a diferencia de los punteros a funcin, los delegados de Visual Basic son un tipo de referencia basado en la clase System.Delegate. Los delegados pueden hacer referencia a los dos mtodos compartidos, mtodos a los que se pueden llamar sin una instancia especfica de una clase, y a mtodos de instancia.

Delegados y eventos

Los delegados son tiles en situaciones donde es necesario un intermediario entre el procedimiento que realiza una llamada y el procedimiento que la recibe. Por ejemplo, puede que desee que un objeto que provoca eventos sea capaz de llamar a diferentes controladores de eventos bajo diferentes circunstancias. Desafortunadamente, el objeto que provoca los eventos no puede saber por adelantado qu controlador de eventos controla un evento especfico. Visual Basic permite asociar dinmicamente los controladores de eventos a los eventos creando un delegado para el usuario cuando usa la instruccin AddHandler. En tiempo de ejecucin, el delegado remite las llamadas al controlador de eventos adecuado. Aunque puede crear sus propios delegados, en la mayora de los casos Visual Basic crea el delegado y se ocupa de los detalles. Por ejemplo, una instruccin Event define de forma implcita una clase delegada denominada <EventName>EventHandler como clase anidada de la clase que contiene la instruccin Event, y con la misma firma que el evento. La instruccin AddressOf crea de forma implcita una instancia de un delegado. Por ejemplo, las siguientes dos lneas de cdigo son equivalentes:

VB C# C++ F# JScript

Copiar AddHandler Button1.Click, AddressOf Me.Button1_Click ' The previous line of code is shorthand for the next line of code. AddHandler Button1.Click, New EventHandler(AddressOf Button1_Click)

Puede utilizar el mtodo abreviado para crear delegados en cualquier lugar donde el compilador pueda determinar el tipo de delegado por el contexto.

Declarar eventos que utilicen un tipo de delegado existente

En algunas situaciones, puede que desee declarar un evento para que utilice un tipo de delegado existente como delegado subyacente. La sintaxis siguiente describe cmo hacerlo:

VB C# C++ F# JScript

Copiar Delegate Sub DelegateType() Event AnEvent As DelegateType

Esto resulta til cuando se desea enrutar diversos eventos hacia el mismo controlador.

Variables delegadas y parmetros

Puede utilizar delegados para otras tareas, no relacionadas con eventos, como un subprocesamiento libre o con procedimientos que necesiten llamar a diferentes versiones de funciones en tiempo de compilacin. Por ejemplo, suponga que tiene una aplicacin de anuncio clasificado que incluye un cuadro de lista con nombres de coches. Los anuncios estn ordenados por ttulos, que normalmente son las marcas de los coches. Un problema con el que puede encontrarse se produce cuando algunos coches incluyen el ao del coche antes de la marca. El problema es que la funcionalidad de ordenacin integrada del cuadro de lista ordena nicamente por cdigos de carcter; primero coloca todos los anuncios que empiezan por el ao y, a continuacin, los anuncios que empiezan por la marca. Para corregir este problema, puede crear un procedimiento de ordenacin en una clase que utilice la ordenacin alfabtica estndar en la mayora de los cuadros de lista, pero que pueda cambiar en tiempo de ejecucin al procedimiento de ordenacin personalizado para anuncios de coches. Para ello, pasa el procedimiento de ordenacin personalizado a la clase de ordenacin en tiempo de ejecucin, utilizando delegados. Cada clase delegada define un constructor al cual se pasa la especificacin de un mtodo de objeto. Un argumento para un constructor delegado debe ser una referencia a un mtodo o una expresin lambda. Para especificar una referencia a un mtodo, utilice la sintaxis siguiente: AddressOf [expression.]methodName El tipo de tiempo de compilacin de expression debe ser el nombre de una clase o interfaz que contenga un mtodo del nombre especificado cuya firma coincida con la firma de la clase delegada. methodName puede ser un mtodo compartido o un mtodo de instancia. Aunque se cree un delegado para el mtodo predeterminado de la clase, methodName no es opcional. Para especificar una expresin lambda, utilice la sintaxis siguiente: Function ([parm como type, parm2 como type2, ...]) expression La firma de la funcin debe coincidir con la del tipo de delegado. Para obtener ms informacin sobre expresiones lambda, vea Expresiones lambda.

Cmo: Invocar un mtodo delegado


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Este ejemplo muestra cmo asociar un mtodo a un delegado e invocar luego este mtodo a travs del delegado.

Cree el delegado y los procedimientos correspondientes


1. Cree un delegado denominado MySubDelegate.

Copiar Delegate Sub MySubDelegate(ByVal x As Integer)


2. Declare una clase que contenga un mtodo con la misma firma que el delegado.

Copiar Class class1 Sub Sub1(ByVal x As Integer) MsgBox("The value of x is: " & CStr(x)) End Sub End Class
3. Defina un mtodo que cree una instancia del delegado e invoque el mtodo asociado al delegado llamando al mtodo Invoke integrado.

Copiar Protected Sub DelegateTest() Dim c1 As New class1 ' Create an instance of the delegate. Dim msd As MySubDelegate = AddressOf c1.Sub1 ' Call the method. msd.Invoke(10)

End Sub

Cmo: Pasar procedimientos a otro procedimiento en Visual Basic


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Este ejemplo muestra cmo se utilizan los delegados para pasar un procedimiento a otro. Un delegado es un tipo que puede utilizar como cualquier otro tipo en Visual Basic. El operador AddressOf devuelve un objeto de delegado cuando se aplica a un nombre de procedimiento. Este ejemplo tiene un procedimiento con un parmetro de delegado que puede llevar una referencia a otro procedimiento obtenido con el operador AddressOf.

Crear el delegado y los procedimientos correspondientes


1. Cree un delegado denominado MathOperator.

VB C# C++ F# JScript

Copiar Delegate Function MathOperator( _ ByVal x As Double, _ ByVal y As Double _ ) As Double

2.

Cree un procedimiento denominado AddNumbers con los parmetros y el valor devuelto que coincidan con aqullos de MathOperator para que coincidan las firmas.

VB C# C++ F# JScript

Copiar

Function AddNumbers( _ ByVal x As Double, _ ByVal y As Double _ ) As Double Return x + y End Function

3.

Cree un procedimiento denominado SubtractNumbers con una firma que coincida con MathOperator.

VB C# C++ F# JScript

Copiar Function SubtractNumbers( _ ByVal x As Double, _ ByVal y As Double _

) As Double Return x - y End Function

4.

Cree un procedimiento denominado DelegateTest que tome un delegado como parmetro. Este procedimiento puede aceptar una referencia para AddNumbers o SubtactNumbers porque sus firmas coinciden con la firma MathOperator.

VB C# C++ F# JScript

Copiar Sub DelegateTest( _ ByVal x As Double, _ ByVal op As MathOperator, _ ByVal y As Double _ )

Dim ret As Double ret = op.Invoke(x, y) ' Call the method. MsgBox(ret) End Sub

5.

Cree un procedimiento denominado Test que llame a DelegateTest una vez con el delegado para AddNumbers como parmetro y, de nuevo, con el delegado para SubtractNumbers como parmetro.

VB C# C++ F# JScript

Copiar Protected Sub Test() DelegateTest(5, AddressOf AddNumbers, 3) DelegateTest(9, AddressOf SubtractNumbers, 3) End Sub

Cuando se llama a Test, muestra en primer lugar el resultado de AddNumbers al actuar sobre 5 y 3, que es 8. A continuacin, se muestra el resultado de SubtractNumbers al actuar sobre 9 y 3, que es 6.

Conversin de delegado flexible


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 La conversin de delegado flexible, incluida en Visual Basic 2008, permite asignar funciones y subrutinas a delegados o controladores de eventos cuando sus firmas no son idnticas. Por tanto, el enlace a los delegados se vuelve coherente con el enlace ya permitido en las llamadas a mtodos.

Parmetros y tipo de valor devuelto

En lugar de la coincidencia exacta de firmas, la conversin flexible requiere que se cumplan las condiciones siguientes cuando Option Strict est establecido en On:

Debe existir una conversin de ampliacin desde el tipo de datos de cada parmetro delegado al tipo de datos del parmetro correspondiente de la funcin asignada o Sub. En el ejemplo siguiente, el delegado Del1 tiene un parmetro, Integer. El parmetro m en las expresiones lambda asignadas debe tener un tipo de datos para el que haya una conversin de ampliacin desde Integer, como Long o Double.

VB C#

C++ F# JScript

Copiar ' Definition of delegate Del1. Delegate Function Del1(ByVal arg As Integer) As Integer

VB C# C++ F# JScript

Copiar

' Valid lambda expression assignments with Option Strict on or off:

' Integer matches Integer. Dim d1 As Del1 = Function(m As Integer) 3

' Integer widens to Long Dim d2 As Del1 = Function(m As Long) 3

' Integer widens to Double Dim d3 As Del1 = Function(m As Double) 3

Slo se permiten las conversiones de restriccin cuando Option Strict est establecido en Off.

VB C# C++ F# JScript

Copiar

' Valid only when Option Strict is off:

Dim d4 As Del1 = Function(m As String) CInt(m) Dim d5 As Del1 = Function(m As Short) m

Debe existir una conversin de ampliacin en la direccin contraria desde el tipo de valor devuelto de la funcin o Sub asignada al tipo de valor devuelto del delegado. En los ejemplos siguientes, el cuerpo de cada expresin lambda asignada se debe evaluar como un tipo de datos que se ampla a Integer, porque el tipo de valor devuelto de del1 es Integer.

VB C# C++ F# JScript

Copiar ' Valid return types with Option Strict on:

' Integer matches Integer. Dim d6 As Del1 = Function(m As Integer) m

' Short widens to Integer. Dim d7 As Del1 = Function(m As Long) CShort(m)

' Byte widens to Integer. Dim d8 As Del1 = Function(m As Double) CByte(m)

Si Option Strict est establecido en Off, se quita la restriccin de ampliacin en ambas direcciones.

VB C# C++ F# JScript

Copiar ' Valid only when Option Strict is set to Off.

' Integer does not widen to Short in the parameter. Dim d9 As Del1 = Function(n As Short) n

' Long does not widen to Integer in the return type. Dim d10 As Del1 = Function(n As Integer) CLng(n)

Omisin de las especificaciones del parmetro

Los delegados flexibles tambin permiten omitir completamente las especificaciones del parmetro en el mtodo asignado:

VB C# C++ F# JScript

Copiar ' Definition of delegate Del2, which has two parameters. Delegate Function Del2(ByVal arg1 As Integer, ByVal arg2 As String) As Integer

VB C# C++ F# JScript

Copiar ' The assigned lambda expression specifies no parameters, even though ' Del2 has two parameters. Because the assigned function in this ' example is a lambda expression, Option Strict can be on or off. ' Compare the declaration of d16, where a standard function is assigned. Dim d11 As Del2 = Function() 3

' The parameters are still there, however, as defined in the delegate. Console.WriteLine(d11(5, "five"))

' Not valid. ' Console.WriteLine(d11()) ' Console.WriteLine(d11(5))

Observe que no puede especificar algunos parmetros y omitir otros.

VB C# C++ F# JScript

Copiar ' Not valid. 'Dim d12 As Del2 = Function(p As Integer) p

La capacidad de omitir parmetros es til en una situacin en la que se define un controlador de eventos, donde estn implicados varios parmetros complejos. No se usan argumentos en algunos controladores de eventos. En su lugar, el controlador tiene directamente acceso al estado del control en el que se registra el evento y omite los argumentos. Los delegados flexibles permiten omitir argumentos en aquellas declaraciones sin ambigedades. En el ejemplo siguiente, el mtodo completo OnClick se puede volver a escribir como RelaxedOnClick.

VB

C# C++ F# JScript

Copiar Sub OnClick(ByVal sender As Object, ByVal e As EventArgs) Handles b.Click MessageBox.Show("Hello World from" + b.Text) End Sub

Sub RelaxedOnClick() Handles b.Click MessageBox.Show("Hello World from" + b.Text) End Sub

Ejemplos de AddressOf

Las expresiones lambda se usan en los ejemplos anteriores para que se vean fcilmente las relaciones entre tipos. Sin embargo, se permite la misma flexibilidad para las asignaciones de delegado que usan AddressOf, Handles o AddHandler. En el siguiente ejemplo, las funciones f1, f2, f3 y f4 se pueden asignar a Del1.

VB C#

C++ F# JScript

Copiar ' Definition of delegate Del1. Delegate Function Del1(ByVal arg As Integer) As Integer

VB C# C++ F# JScript

Copiar ' Definitions of f1, f2, f3, and f4. Function f1(ByVal m As Integer) As Integer

End Function

Function f2(ByVal m As Long) As Integer End Function

Function f3(ByVal m As Integer) As Short End Function

Function f4() As Integer End Function

VB C# C++ F# JScript

Copiar ' Assignments to function delegate Del1.

' Valid AddressOf assignments with Option Strict on or off:

' Integer parameters of delegate and function match. Dim d13 As Del1 = AddressOf f1

' Integer delegate parameter widens to Long. Dim d14 As Del1 = AddressOf f2

' Short return in f3 widens to Integer. Dim d15 As Del1 = AddressOf f3

El ejemplo siguiente slo es vlido cuando Option Strict est establecido en Off.

VB C# C++ F# JScript

Copiar ' If Option Strict is Off, parameter specifications for f4 can be omitted.

Dim d16 As Del1 = AddressOf f4

' Function d16 still requires a single argument, however, as specified ' by Del1. Console.WriteLine(d16(5))

' Not valid. 'Console.WriteLine(d16()) 'Console.WriteLine(d16(5, 3))

Colocar valores devueltos de una funcin

La conversin de delegado flexible permite asignar una funcin a un delegado Sub, omitiendo as el valor devuelto de la funcin. Sin embargo, no se puede asignar un Sub a un delegado de funcin. En el ejemplo siguiente, la direccin de funcin doubler se asigna al delegado SubDel3.

VB C# C++ F# JScript

Copiar ' Definition of Sub delegate Del3. Delegate Sub Del3(ByVal arg1 As Integer)

' Definition of function doubler, which both displays and returns the ' value of its integer parameter. Function doubler(ByVal p As Integer) As Integer Dim times2 = 2 * p Console.WriteLine("Value of p: " & p) Console.WriteLine("Double p: Return times2 End Function " & times2)

VB C# C++ F# JScript

Copiar

' You can assign the function to the Sub delegate: Dim d17 As Del3 = AddressOf doubler

' You can then call d17 like a regular Sub procedure. d17(5)

' You cannot call d17 as a function. It is a Sub, and has no ' return value. ' Not valid. 'Console.WriteLine(d17(5))

Interfaces en Visual Basic


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Las Interfaces definen las propiedades, mtodos y eventos que pueden implementar las clases. Las interfaces le permiten definir caractersticas como grupos pequeos de propiedades, mtodos y eventos estrechamente relacionados; de esta forma se reducen los problemas de compatibilidad, ya que pueden desarrollarse implementaciones mejoradas para las interfaces sin poner en peligro el cdigo existente. Se pueden agregar nuevas caractersticas en cualquier momento, mediante el desarrollo de implementaciones e interfaces adicionales. En versiones anteriores de Visual Basic, poda utilizar interfaces pero no crearlas directamente. En esta versin, puede utilizar la instruccin Interface, que permite definir interfaces reales como entidades diferenciadas a partir de clases e implementarlas con una versin mejorada de la palabra clave Implements.

Informacin general sobre interfaces


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Las interfaces, como las clases, definen un conjunto de propiedades, mtodos y eventos. Pero de forma contraria a las clases, las interfaces no proporcionan implementacin. Se implementan como clases y se definen como entidades separadas de las clases. Una interfaz representa un contrato, en el cual una clase que implementa una interfaz debe implementar cualquier aspecto de dicha interfaz exactamente como est definido. Con las interfaces, puede definir caractersticas como grupos pequeos de miembros relacionados estrechamente. Puede desarrollar implementaciones mejoradas para sus interfaces sin poner en peligro el cdigo existente, minimizando de este modo los problemas de compatibilidad. Tambin puede agregar nuevas caractersticas en cualquier momento, mediante el desarrollo de implementaciones e interfaces adicionales. A pesar de que las implementaciones de interfaces pueden evolucionar, las propias interfaces no pueden cambiarse una vez editadas. Los cambios que se realicen en una interfaz editada pueden interrumpir el cdigo existente. Si piensa en una interfaz como si fuera un contrato, resulta evidente que ambas partes del contrato tienen un papel especfico. El editor de una interfaz se compromete a no cambiar nunca la interfaz, y la persona que la implementa se compromete a implementarla exactamente tal y como haya sido diseada. En versiones anteriores de Visual Basic, poda utilizar interfaces pero no crearlas directamente. Ahora puede definir verdaderas interfaces mediante la instruccin Interface e implementarlas con una versin mejorada de la palabra clave Implements.

Actualizacin: noviembre 2007 Las definiciones de interfaz se encuentran dentro de las instrucciones Interface y End Interface. Despus de la instruccin Interface, puede agregar una instruccin Inherits opcional que proporciona una lista de

una o varias interfaces heredadas. Las instrucciones Inherits deben ir antes que el resto de instrucciones de una declaracin, a excepcin de los comentarios. El resto de instrucciones de una definicin de interfaz deberan ser instrucciones Event, Sub, Function, Property, Interface, Class, Structure y Enum. Las interfaces no pueden contener cdigo de implementacin ni instrucciones asociadas a cdigo de implementacin, como End Sub o End Property. En un espacio de nombres, las instrucciones de interfaz son de manera predeterminada Friend, pero tambin se pueden declarar explcitamente como Public o Friend. Las interfaces definidas dentro de las clases, mdulos, interfaces y estructuras son de manera predeterminada Public, pero tambin se pueden declarar explcitamente como Public, Friend, Protected o Private.

Nota:
La palabra clave Shadows se puede aplicar a todos los miembros de la interfaz. La palabra clave Overloads se puede aplicar a las instrucciones declaradas Sub, Function y Property en la definicin de una interfaz. Adems, las instrucciones Property pueden tener los modificadores Default, ReadOnly o WriteOnly. No se permite ninguno del resto de los modificadores: Public, Private, Friend, Protected, Shared, Overrides, MustOverride o Overridable. Para obtener ms informacin, vea Contextos de declaracin y niveles de acceso predeterminados.

Palabra clave Implements e instruccin Implements


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 La palabra reservada Implements de Visual Basic se utiliza de dos formas. La instruccin Implements significa que una clase o estructura implementa una interfaz. La palabra clave Implements significa que un miembro de clase o de estructura implementa un miembro de interfaz especfico.

Instruccin de implementacin

Si una clase o estructura implementa una o ms interfaces, debe incluir la instruccin Implements inmediatamente despus de la instruccin Class o Structure. La instruccin Implements exige que una lista separada por comas de interfaces sea implementada por una clase. La clase o estructura debe implementar todos los miembros de interfaz mediante la palabra clave Implements.

La palabra clave Implements

La palabra clave Implements requiere una lista separada por comas de los miembros de la interfaz que deben implementarse. Por lo general, se especifica solamente un nico miembro de interfaz, pero se pueden especificar varios miembros. La especificacin de un miembro de interfaz consta del nombre de la interfaz, que debe especificarse en una instruccin Implements dentro de la clase, un punto y el nombre del evento, propiedad o funcin miembro que debe implementarse. El nombre de un miembro que implementa un miembro de interfaz puede utilizar cualquier identificador permitido y no se limita a la convencin InterfaceName_MethodName que se utilizaba en las versiones anteriores de Visual Basic. Por ejemplo, el cdigo siguiente muestra cmo declarar una subrutina denominada Sub1 que implementa un mtodo de una interfaz:

VB C# C++ F# JScript

Copiar Class Class1 Implements interfaceclass.interface2

Sub Sub1(ByVal i As Integer) Implements interfaceclass.interface2.Sub1 End Sub End Class

Los tipos de parmetro y de valores devueltos del miembro que realiza la implementacin deben coincidir con la propiedad de interfaz o la declaracin de miembro de la interfaz. La forma ms habitual de implementar un elemento de una interfaz es con un miembro que tenga el mismo nombre que la interfaz, como se muestra en el ejemplo anterior. Para declarar la implementacin de un mtodo de interfaz, puede utilizar cualquier atributo permitido en las declaraciones de mtodo de instancia, incluidos Overloads, Overrides, Overridable, Public, Private, Protected, Friend, Protected Friend, MustOverride, Default y Static. El atributo Shared no est permitido, ya que define una clase en lugar de un mtodo de instancia. Con Implements tambin puede crear un nico mtodo que implemente varios mtodos definidos en una interfaz, como en el ejemplo siguiente:

VB C# C++ F# JScript

Copiar Class Class2 Implements I1, I2

Protected Sub M1() Implements I1.M1, I1.M2, I2.M3, I2.M4 End Sub End Class

Puede utilizar un miembro privado para implementar un miembro de interfaz. Cuando un miembro privado implementa un miembro de una interfaz, el miembro pasa a estar disponible por medio de la interfaz, aunque no est disponible directamente en las variables de objeto para la clase.

Ejemplos de implementacin de interfaces en Visual Basic


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Las clases que implementan una interfaz deben implementar todas sus propiedades, mtodos y eventos. El ejemplo siguiente define dos interfaces. La segunda interfaz, Interface2, hereda Interface1 y define un mtodo y una propiedad adicional.

VB C# C++

F# JScript

Copiar Interface Interface1 Sub sub1(ByVal i As Integer) End Interface

' Demonstrates interface inheritance. Interface Interface2 Inherits Interface1 Sub M1(ByVal y As Integer) ReadOnly Property Num() As Integer End Interface

El ejemplo siguiente implementa Interface1, la interfaz definida en el ejemplo anterior:

VB C# C++ F#

JScript

Copiar Public Class ImplementationClass1 Implements Interface1 Sub Sub1(ByVal i As Integer) Implements Interface1.sub1 ' Insert code here to implement this method. End Sub End Class

El ejemplo final implementa Interface2, incluyendo un mtodo heredado de Interface1:

VB C# C++ F# JScript

Copiar Public Class ImplementationClass2 Implements Interface2 Dim INum As Integer = 0 Sub sub1(ByVal i As Integer) Implements Interface2.sub1 ' Insert code here that implements this method. End Sub Sub M1(ByVal x As Integer) Implements Interface2.M1 ' Insert code here to implement this method. End Sub

ReadOnly Property Num() As Integer Implements _ Interface2.Num Get Num = INum End Get End Property End Class

Cundo se deben utilizar interfaces


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007

Las interfaces son una herramienta de programacin eficaz porque le permiten separar la definicin de objetos de su implementacin. La herencia de clases y las interfaces tienen ventajas e inconvenientes, y puede que al final decida utilizar una combinacin de ambas en sus proyectos. Esta pgina y Cundo utilizar la herencia le ayudarn a determinar qu enfoque es mejor para su situacin.

Flexibilidad en la implementacin

Existen otras razones por las que se podra desear utilizar interfaces en lugar de la herencia de clases:

Las interfaces admiten mejor las situaciones en las cuales las aplicaciones necesitan el mayor nmero de tipos de objetos no relacionados posible para proporcionar determinadas funciones. Las interfaces son ms flexibles que las clases de base, porque puede definir una nica implementacin que puede implementar interfaces mltiples. Las interfaces son mejores en situaciones en las que no es necesario heredar una implementacin de una clase de base. Las interfaces son tiles cuando no se puede usar la herencia de clases. Por ejemplo, las estructuras no pueden heredarse de las clases, pero pueden implementar interfaces.

Cmo: Crear e implementar interfaces


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Como se explica en Informacin general sobre interfaces, las interfaces describen las propiedades, mtodos y eventos de una clase sin proporcionar ninguna implementacin.

Para crear una interfaz


1. Defina la interfaz agregndole cdigo, de tal forma que empiece con la palabra clave Interface y el nombre de la interfaz, y que acabe con la instruccin End Interface. Por ejemplo, el siguiente cdigo define una interfaz denominada IAsset.

VB C# C++ F# JScript

Copiar Interface IAsset End Interface

2.

Agregue instrucciones que definan las propiedades, mtodos y eventos que sean compatibles con la interfaz. Por ejemplo, el siguiente cdigo define una funcin, una propiedad y un evento.

VB C# C++

F# JScript

Copiar Interface IAsset Event ComittedChange(ByVal Success As Boolean) Property Division() As String Function GetID() As Integer End Interface

Para implementar una interfaz


1. 2. Si la interfaz que est implementando no forma parte del proyecto, agregue una referencia al ensamblado que contiene la interfaz. Cree una clase nueva que implemente la interfaz, e incluya la palabra clave Implements en la lnea que sigue al nombre de clase. Por ejemplo, para implementar la interfaz IAsset, podra darle a la clase de implementacin el nombre Computer, como en el cdigo siguiente.

VB C# C++ F#

JScript

Copiar Class Computer Implements IAsset End Class

3.

Agregue procedimientos para implementar las propiedades, mtodos y eventos de la clase como en el cdigo siguiente, que se basa en el ejemplo del paso anterior:

VB C# C++ F# JScript

Copiar

Class Computer Implements IAsset

Public Event ComittedChange(ByVal Success As Boolean) _ Implements IAsset.ComittedChange

Private divisionValue As String

Public Property Division() As String _ Implements IAsset.Division

Get Return divisionValue End Get Set(ByVal value As String) divisionValue = value RaiseEvent ComittedChange(True) End Set End Property

Private IDValue As Integer

Public Function GetID() As Integer _ Implements IAsset.GetID

Return IDValue End Function

Public Sub New(ByVal Division As String, ByVal ID As Integer) Me.divisionValue = Division Me.IDValue = ID End Sub End Class

Tutorial: Crear e implementar interfaces


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Las interfaces describen las caractersticas de las propiedades, los mtodos y los eventos, pero dejan los detalles de la implementacin para las estructuras o clases. Este tutorial explica cmo declarar e implementar una interfaz.

Nota:
Los cuadros de dilogo y los comandos de men que se ven pueden diferir de los descritos en la Ayuda, dependiendo de los valores de configuracin o de edicin activos. Para cambiar la configuracin, seleccione Importar y exportar configuraciones en el men Herramientas. Para obtener ms informacin, vea Valores de configuracin de Visual Studio.

Para definir una interfaz


1. 2. 3. 4. Abra un nuevo proyecto Aplicacin para Windows de Visual Basic. Agregue un mdulo nuevo al proyecto haciendo clic en Agregar mdulo en el men Proyecto. Asigne al mdulo el nombre Module1.vb y haga clic en Agregar. Aparecer el cdigo del mdulo nuevo. Defina una interfaz con el nombre TestInterface dentro de Module1; para ello, escriba Interface TestInterface entre las instrucciones Module y End Module y presione ENTRAR. El Editor de

5.

cdigo aplica una sangra delante de la palabra clave Interface y agrega una instruccin End Interface para formar un bloque de cdigo. Defina una propiedad, un mtodo y un evento para la interfaz; para ello, site el siguiente cdigo entre las instrucciones Interface y End Interface:

VB C# C++ F# JScript

Copiar Property Prop1() As Integer Sub Method1(ByVal X As Integer) Event Event1()

Implementacin

Puede notar que la sintaxis utilizada para declarar los miembros de la interfaz es diferente de la sintaxis utilizada para declarar los miembros de la clase. Esta diferencia refleja el hecho de que las interfaces no pueden contener cdigo de implementacin.

Para implementar la interfaz


1. Agregue una clase denominada ImplementationClass; para ello, agregue la siguiente instruccin a Module1 despus de la instruccin End Interface pero antes de la instruccin End Module y, a continuacin, presione ENTRAR:

VB C# C++ F# JScript

Copiar Class ImplementationClass

Si est trabajando dentro del entorno de desarrollo integrado, el Editor de cdigo proporciona la instruccin End Class correspondiente al presionar ENTRAR. 2. Agregue la siguiente instruccin Implements a ImplementationClass, que da nombre a la interfaz que implementa la clase:

VB C# C++ F# JScript

Copiar Implements TestInterface

Cuando se muestra separada de otros elementos en la parte superior de la clase o estructura, la instruccin Implements indica que la clase o estructura implementa una interfaz. Si est trabajando dentro del entorno de desarrollo integrado, el Editor de cdigo implementa los miembros de clase requeridos por TestInterface al presionar ENTRAR, y se puede omitir el paso siguiente. 3. Si no est trabajando dentro del entorno de desarrollo integrado, debe implementar todos los miembros de la interfaz MyInterface. Agregue el cdigo siguiente a ImplementationClass para implementar Event1, Method1 y Prop1:

VB C# C++ F# JScript

Copiar Event Event1() Implements TestInterface.Event1

Public Sub Method1(ByVal X As Integer) Implements TestInterface.Method1 End Sub

Public Property Prop1() As Integer Implements TestInterface.Prop1 Get End Get Set(ByVal value As Integer) End Set End Property

La instruccin Implements asigna un nombre a la interfaz y al miembro de la interfaz que se est implementando. 4. Para finalizar la definicin de Prop1, agregue un campo privado a la clase que almacen el valor de la propiedad:

VB C# C++ F# JScript

Copiar ' Holds the value of the property. Private pval As Integer

Devuelva el valor de pval desde el descriptor de acceso get de la propiedad.

VB C# C++

F# JScript

Copiar Return pval

Establezca el valor de pval en el descriptor de acceso set de la propiedad.

VB C# C++ F# JScript

Copiar pval = value

5.

Para finalizar la definicin de Method1, agregue el cdigo siguiente:

VB C# C++ F# JScript

Copiar MsgBox("The X parameter for Method1 is " & X) RaiseEvent Event1()

Para probar la implementacin de la interfaz


1. Haga clic con el botn secundario del mouse (ratn) en el formulario de inicio del proyecto en el Explorador de soluciones y haga clic en Ver cdigo. El editor mostrar la clase del formulario de inicio. De manera predeterminada, el formulario de inicio se denomina Form1. Agregue el siguiente campo testInstance a la clase Form1:

2.

VB C# C++ F# JScript

Copiar Dim WithEvents testInstance As TestInterface

Al declarar testInstance como WithEvents, la clase Form1 puede controlar sus eventos. 3. Agregue el siguiente controlador de eventos a la clase Form1 para controlar los eventos desencadenados por testInstance:

VB C# C++

F# JScript

Copiar Sub EventHandler() Handles testInstance.Event1 MsgBox("The event handler caught the event.") End Sub

4.

Agregue una subrutina denominada Test a la clase Form1 para probar la clase de implementacin:

VB C# C++ F# JScript

Copiar Sub Test() ' Create an instance of the class.

Dim T As New ImplementationClass ' Assign the class instance to the interface. ' Calls to the interface members are ' executed through the class instance. testInstance = T ' Set a property. testInstance.Prop1 = 9 ' Read the property. MsgBox("Prop1 was set to " & testInstance.Prop1) ' Test the method and raise an event.

testInstance.Method1(5) End Sub

El procedimiento Test crea una instancia de la clase que implementa MyInterface, asigna esa instancia al campo testInstance, define una propiedad y ejecuta un mtodo a travs de la interfaz. 5. Agregue cdigo para llamar al procedimiento Test desde el procedimiento Form1 Load del formulario de inicio:

VB C#

C++ F# JScript

Copiar Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles MyBase.Load Test() ' Test the class. End Sub

6.

Ejecute el procedimiento Test presionando F5. Aparecer el mensaje "Prop1 se ha definido como 9". Tras hacer clic en Aceptar, aparecer el mensaje "El parmetro X de Method1 es 5". Al hacer clic en Aceptar, aparecer el mensaje "El controlador de eventos ha interceptado el evento".

Fundamentos de la herencia
Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007

La instruccin Inherits se utiliza para declarar una nueva clase, denominada clase derivada, basada en una clase existente conocida como clase base. Las clases derivadas heredan, y pueden extender, las propiedades, mtodos, eventos, campos y constantes definidos en la clase base. En la siguiente seccin se describen algunas de las reglas de herencia, as como los modificadores que se pueden utilizar para cambiar la forma en que las clases heredan o son heredadas:

De forma predeterminada, todas las clases son heredables a menos que se marquen con la palabra clave NotInheritable. Las clases pueden heredar de otras clases del proyecto o de clases en otros ensamblados a los que hace referencia el proyecto. A diferencia de los lenguajes que permiten la herencia mltiple, Visual Basic solamente permite la herencia simple en las clases; es decir, las clases derivadas solo pueden tener una clase base. Aunque no se permite la herencia mltiple en las clases, stas pueden implementar mltiples interfaces, lo que permite lograr de manera eficaz los mismos fines. Para evitar la exposicin de elementos restringidos en una clase base, el tipo de acceso de una clase derivada debe ser igual o ms restrictivo que el de su clase base. Por ejemplo, una clase Public no puede heredar una clase Friend o Private, y una clase Friend no puede heredar una clase Private.

Modificadores de herencia

Visual Basic presenta las siguientes instrucciones y modificadores de nivel de clase para ofrecer compatibilidad con la herencia:

Instruccin Inherits: especifica la clase base. Modificador NotInheritable: impide que los programadores utilicen la clase como clase base. Modificador MustInherit: especifica que la clase slo se debe utilizar como clase base. Las instancias de las clases MustInherit no se pueden crear directamente; slo se pueden crear como instancias de clase base de una clase derivada. Otros lenguajes de programacin, como C++ y C#, utilizan el trmino clase abstracta para describir tal clase.

Reemplazar propiedades y mtodos en clases derivadas

De forma predeterminada, una clase derivada hereda los mtodos y propiedades de su clase base. Si una propiedad o mtodo heredados tienen que comportarse de manera diferente en la clase derivada, se pueden invalidar. Es decir, se puede definir una nueva implementacin del mtodo en la clase derivada. Los siguientes modificadores se utilizan para controlar cmo se reemplazan propiedades y mtodos:

Overridable: permite reemplazar una propiedad o un mtodo de una clase en una clase derivada. Overrides: reemplaza una propiedad o un mtodo Overridable definido en la clase base. NotOverridable: evita que una propiedad o un mtodo se invaliden en una clase que hereda. De forma predeterminada, los mtodos Public son NotOverridable. MustOverride: requiere que una clase derivada reemplace una propiedad o un mtodo. Cuando se utiliza la palabra clave MustOverride, la definicin del mtodo est formada simplemente por la instruccin Sub, Function o Property. No se permite ninguna otra instruccin y no hay

especficamente ninguna instruccin End Sub o End Function. Los mtodos MustOverride se deben declarar en las clases MustInherit. Para obtener ms informacin sobre los mtodos de reemplazo, consulte Invalidar propiedades y mtodos.

La palabra clave MyBase

Puede utilizar la palabra clave MyBase para llamar a mtodos de una clase base cuando invalide mtodos en una clase derivada. Por ejemplo, suponga que disea una clase derivada que reemplaza un mtodo heredado de la clase base. El mtodo reemplazado puede llamar al mtodo de la clase base y modificar el valor devuelto como se muestra en el fragmento de cdigo siguiente:

VB C# C++ F# JScript

Copiar Class DerivedClass Inherits BaseClass Public Overrides Function CalculateShipping( _ ByVal Dist As Double, _ ByVal Rate As Double) _ As Double

' Call the method in the base class and modify the return value. Return MyBase.CalculateShipping(Dist, Rate) * 2 End Function End Class

En la lista siguiente se describen las restricciones de uso de MyBase:

MyBase hace referencia a la clase base inmediata y a sus miembros heredados. No se puede utilizar para tener acceso a miembros Private de la clase. MyBase es una palabra clave, no un objeto real. MyBase no se puede asignar a una variable, pasar a procedimientos o utilizar en una comparacin Is. No es necesario definir el mtodo al que certifica MyBase en la clase base inmediata; puede definirse en una clase base heredada indirectamente. Para compilar correctamente una referencia certificada mediante MyBase, alguna clase base debe contener un mtodo que se corresponda con el nombre y los tipos de los parmetros que aparecen en la llamada. No puede utilizar MyBase para llamar a mtodos de clase base con el modificador MustOverride. No se puede utilizar MyBase para calificarse a s misma. Por tanto, el siguiente cdigo no es vlido: MyBase.MyBase.BtnOK_Click()

No se puede utilizar MyBase en mdulos. No se puede utilizar MyBase para tener acceso a miembros de clase base marcados como Friend si la clase base est en un ensamblado diferente.

La palabra clave MyClass

La palabra clave MyClass permite llamar a un mtodo Overridable implementado en la clase y asegurarse de que se llama a la implementacin del mtodo en esta clase y no a la de un mtodo invalidado en una clase derivada.

MyClass es una palabra clave, no un objeto real. MyClass no se puede asignar a una variable, pasar a procedimientos o utilizar en una comparacin Is. MyClass hace referencia a la clase base inmediata y a sus miembros heredados. MyClass puede utilizarse como calificador de miembros Shared. MyClass no se puede utilizar en mdulos estndar. MyClass puede utilizarse para calificar un mtodo que est definido en un clase base y que no tiene ninguna implementacin del mtodo proporcionado en esa clase. Este tipo de referencia tiene el mismo significado que MyBase.Mtodo.

Cmo: Crear clases derivadas


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 La instruccin Inherits hace que una clase herede todos los miembros no privados de la clase especificada.

Para heredar de otra clase

Agregue una instruccin Inherits (con el nombre de una clase que desee utilizar como clase base) como primera instruccin de la clase derivada. La instruccin Inherits debe ser la primera instruccin sin comentario despus de la instruccin de clase.

Ejemplo

El ejemplo siguiente define dos clases. La primera es una clase base que tiene dos mtodos. La segunda hereda los dos mtodos de la clase base, reemplaza el segundo mtodo y define un campo denominado Field.

VB C# C++ F# JScript

Copiar Class Class1 Sub Method1() MsgBox("This is a method in the base class.") End Sub Overridable Sub Method2() MsgBox("This is another method in the base class.") End Sub End Class

Class Class2 Inherits Class1 Public Field2 As Integer Overrides Sub Method2() MsgBox("This is a method in a derived class.") End Sub End Class

Protected Sub TestInheritance() Dim C1 As New Class1 Dim C2 As New Class2 C1.Method1() ' Calls a method in the base class. C1.Method2() ' Calls another method from the base class. C2.Method1() ' Calls an inherited method from the base class.

C2.Method2() ' Calls a method from the derived class. End Sub

Al ejecutar el procedimiento TestInheritance, aparecen los siguientes mensajes: This is a method in the base class. This is another method in the base class. This is a method in the base class. This is a method in a derived class.

Cundo utilizar la herencia


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 La herencia es un concepto de programacin til, pero es fcil utilizarlo de manera poco adecuada. A menudo, las interfaces solucionan mejor la situacin. Este tema y Cundo se deben utilizar interfaces le ayudan a entender cundo se debe utilizar cada enfoque. La herencia es una buena opcin cuando:

La jerarqua de herencia representa una relacin de identidad y no una relacin de pertenencia. Se puede volver a utilizar cdigo de las clases base. Es necesario aplicar la misma clase y los mismos mtodos a tipos de datos diferentes. La jerarqua de clases es poco profunda y es poco probable que otros programadores agreguen muchos ms niveles. Desea realizar cambios globales en clases derivadas modificando una clase base.

Estas consideraciones se explican en este orden a continuacin.

Herencia y relaciones de identidad

Dos maneras de mostrar las relaciones de clase en la programacin orientada a objetos son las relaciones de identidad y de pertenencia. En una relacin de identidad, la clase derivada es claramente un tipo de clase base. Por ejemplo, una clase denominada PremierCustomer representa una relacin de tipo identidad con una clase base denominada Customer, puesto que un cliente principal es un cliente. No obstante, una clase denominada CustomerReferral representa una relacin de pertenencia con la clase Customer porque una cartera de clientes tiene un cliente, pero no es un tipo de cliente. Los objetos de una jerarqua de herencia deben tener una relacin de identidad con la clase base puesto que heredan los campos, propiedades, mtodos y eventos definidos en dicha clase. Las clases que representan una relacin de pertenencia con otras clases no son vlidas para jerarquas de herencia debido a que podran heredar propiedades y mtodos inadecuados. Por ejemplo, si la clase CustomerReferral se derivase de la clase Customer descrita anteriormente, podra heredar propiedades que no tendran sentido, como ShippingPrefs y LastOrderPlaced. Las relaciones de pertenencia como sta deben representarse mediante clases o interfaces no relacionadas. La siguiente ilustracin muestra ejemplos de relaciones de tipo "es un" y "tiene un".

Clases base y reutilizacin de cdigo

Otra razn para usar la herencia es la ventaja de poder reutilizar el cdigo. Las clases bien diseadas, una vez depuradas, pueden utilizarse una y otra vez como base de nuevas clases. Un ejemplo comn de reutilizacin eficaz de cdigo est relacionado con bibliotecas que administran estructuras de datos. Por ejemplo, suponga que tiene una gran aplicacin comercial que administra varias clases de listas en la memoria. Una es una copia en memoria de la base de datos de clientes, que se lee desde una base de datos al iniciar la sesin para conseguir mayor velocidad. La estructura de datos tendra un aspecto similar al siguiente:

VB C# C++ F# JScript

Copiar Class CustomerInfo Protected PreviousCustomer As CustomerInfo Protected NextCustomer As CustomerInfo Public ID As Integer Public FullName As String

Public Sub InsertCustomer(ByVal FullName As String) ' Insert code to add a CustomerInfo item to the list. End Sub

Public Sub DeleteCustomer() ' Insert code to remove a CustomerInfo item from the list. End Sub

Public Function GetNextCustomer() As CustomerInfo ' Insert code to get the next CustomerInfo item from the list. Return NextCustomer End Function

Public Function GetPrevCustomer() As CustomerInfo 'Insert code to get the previous CustomerInfo item from the list. Return PreviousCustomer End Function End Class

La aplicacin tambin podra tener una lista similar de productos que el usuario ha agregado a una lista del carro de la compra, como se muestra en el siguiente fragmento de cdigo:

VB C# C++ F# JScript

Copiar

Class ShoppingCartItem Protected PreviousItem As ShoppingCartItem Protected NextItem As ShoppingCartItem Public ProductCode As Integer Public Function GetNextItem() As ShoppingCartItem ' Insert code to get the next ShoppingCartItem from the list. Return NextItem End Function End Class

Aqu puede ver un modelo: dos listas se comportan del mismo modo (inserciones, eliminaciones y recuperaciones) pero funcionan con tipos de datos diferentes. Mantener dos bases de cdigo para realizar esencialmente las mismas funciones no es eficaz. La solucin ms eficaz consiste en separar la administracin de listas en su propia clase y despus heredar de esa clase para diferentes tipos de datos:

VB C# C++ F# JScript

Copiar

Class ListItem Protected PreviousItem As ListItem Protected NextItem As ListItem Public Function GetNextItem() As ListItem ' Insert code to get the next item in the list. Return NextItem End Function Public Sub InsertNextItem() ' Insert code to add a item to the list. End Sub

Public Sub DeleteNextItem() ' Insert code to remove a item from the list. End Sub

Public Function GetPrevItem() As ListItem 'Insert code to get the previous item from the list. Return PreviousItem End Function End Class

La clase ListItem slo tiene que ser depurada una vez. Despus podr generar clases que la utilicen sin tener que pensar nunca ms sobre la administracin de listas. Por ejemplo:

VB C# C++ F# JScript

Copiar Class CustomerInfo Inherits ListItem Public ID As Integer Public FullName As String End Class Class ShoppingCartItem Inherits ListItem Public ProductCode As Integer End Class

Aunque la reutilizacin de cdigo basado en la herencia es una herramienta eficaz, tambin tiene riesgos asociados. Incluso los sistemas mejor diseados cambian a veces de tal modo que los diseadores no podran prever. A veces, los cambios en una jerarqua de clases existente pueden tener consecuencias no deseadas; en la seccin Cambios en el diseo de la clase base despus de la implementacin de "El problema de fragilidad de la clase base" se describen algunos ejemplos.

Clases derivadas intercambiables

Las clases derivadas de una jerarqua de clases pueden a veces intercambiarse con la clase base, un proceso denominado polimorfismo basado en la herencia. Este enfoque combina las mejores caractersticas del polimorfismo basado en la interfaz con la opcin de reutilizar o reemplazar cdigo de una clase base. As, esto podra ser til en un paquete de dibujo. Por ejemplo, considere el siguiente fragmento de cdigo, que no utiliza herencia:

VB C# C++ F# JScript

Copiar Sub Draw(ByVal Shape As DrawingShape, ByVal X As Integer, _ ByVal Y As Integer, ByVal Size As Integer)

Select Case Shape.type Case shpCircle ' Insert circle drawing code here. Case shpLine ' Insert line drawing code here. End Select End Sub

Este enfoque presenta algunos problemas. Si alguien decide agregar una opcin de elipse posteriormente, ser necesario modificar el cdigo fuente; puede ocurrir que los usuarios a los que va dirigido ni siquiera tengan acceso al cdigo fuente. Un problema ms sutil consiste en que para dibujar una elipse se necesita otro parmetro (las elipses tienen un dimetro principal y uno secundario) que no sera relevante para el caso de la lnea. Si alguien desea agregar una polilnea (mltiples lneas conectadas), entonces se agregara otro parmetro que no sera relevante para otros casos. La herencia resuelve la mayora de estos problemas. Las clases base bien diseadas dejan la implementacin de mtodos especficos para las clases derivadas, de modo que se pueda incluir cualquier forma. Otros programadores pueden implementar mtodos en clases derivadas con la documentacin de la clase base. Otros elementos de clase (como las coordenadas x e y) se pueden integrar en la clase base porque todas las descendientes los utilizan. Por ejemplo, Draw podra ser un mtodo MustOverride:

VB C# C++ F# JScript

Copiar MustInherit Class Shape Public X As Integer Public Y As Integer MustOverride Sub Draw()

End Class

Despus podra agregar los elementos necesarios a esa clase para las diferentes formas. Por ejemplo, una clase Line podra necesitar nicamente un campo Length:

VB C# C++ F# JScript

Copiar Class Line Inherits Shape Public Length As Integer Overrides Sub Draw() ' Insert code here to implement Draw for this shape. End Sub End Class

Este planteamiento es til debido a que otros programadores que no tienen acceso al cdigo fuente pueden extender la clase base con nuevas clases derivadas segn sea necesario. Por ejemplo, una clase denominada Rectangle podra derivarse de la clase Line:

VB C# C++ F# JScript

Copiar Class Rectangle Inherits Line Public Width As Integer Overrides Sub Draw() ' Insert code here to implement Draw for the Rectangle shape. End Sub End Class

En este ejemplo se muestra cmo se puede pasar de clases de propsito general a clases muy especficas mediante la implementacin de detalles en cada nivel. En este punto podra ser conveniente volver a evaluar si la clase derivada realmente representa una relacin de identidad o, por el contrario, es una relacin de pertenencia. Si la nueva clase de rectngulo

se compone solamente de lneas, entonces la herencia no es la mejor opcin. No obstante, si el nuevo rectngulo es una lnea con una propiedad de ancho, entonces se mantiene la relacin de identidad.

Jerarquas de clases poco profundas

La herencia se adapta mejor a jerarquas de clases relativamente poco profundas. Las jerarquas de clases complejas y profundas en exceso pueden ser difciles de desarrollar. La decisin de utilizar una jerarqua de clases implica sopesar sus ventajas y su complejidad. Como norma general, las jerarquas deberan limitarse a seis niveles o menos. No obstante, la profundidad mxima de una jerarqua de clases concreta depende de varios factores, incluida la complejidad de cada nivel.

Cambios globales en clases derivadas a travs de la clase base

Una de las caractersticas ms eficaces de la herencia es la posibilidad de realizar cambios en una clase base que se propagan a las clases derivadas. Si se usa con cuidado, puede actualizarse la implementacin de un solo mtodo y decenas, e incluso cientos, de clases derivadas podrn utilizar el nuevo cdigo. No obstante, esta prctica puede resultar peligrosa puesto que tales cambios podran generar problemas en clases heredadas diseadas por otras personas. Debe tenerse cuidado para asegurarnos de que la nueva clase es compatible con las clases que utilizan la original. Concretamente, debe evitarse cambiar el nombre o el tipo de los miembros de la clase base. Suponga, por ejemplo, que disea una clase base con un campo de tipo Integer para almacenar la informacin de cdigo postal, y que otros programadores han creado clases derivadas que utilizan el campo de cdigo postal heredado. Suponga adems que el campo de cdigo postal almacena cinco dgitos y que la oficina de correos ha ampliado los cdigos postales con un guin y cuatro dgitos adicionales. En el peor de los casos, podra modificar el campo en la clase base para almacenar una cadena de diez caracteres, pero otros programadores tendran que cambiar y volver a compilar las clases derivadas para utilizar el tamao y el tipo de datos nuevos. La forma ms segura de cambiar una clase base es simplemente agregar nuevos miembros. Por ejemplo, podra agregar un nuevo campo para almacenar cuadro dgitos ms en el ejemplo de cdigo postal descrito anteriormente. De esta forma, las aplicaciones cliente pueden actualizarse para que utilicen el nuevo campo sin interrumpir las aplicaciones existentes. Esta posibilidad de extender clases base en una jerarqua de herencia es una ventaja importante que no existe con interfaces.

Herencia y .NET Framework


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Las aplicaciones de Visual Studio pueden utilizar muchas de las clases que se encuentran en .NET Framework como clases base. Las clases de atributo, por ejemplo, siempre estn basadas en la clase Attribute. Otras clases base tiles de .NET Framework incluyen Component que se hereda para definir los componentes y Exception que se hereda para definir las clases de excepcin personalizadas. .NET Framework es ms que un origen para las clases base; garantiza la compatibilidad entre clases creadas con lenguajes de programacin diferentes. las clases de Visual Basic pueden heredar de las clases en ensamblados creados por cualquier lenguaje admitido por Visual Studio. Las clases que crea en Visual Basic tambin se pueden utilizar como clases base por otros lenguajes de programacin de .NET Framework.

Tutorial: Implementar la herencia mediante objetos COM


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Se pueden derivar clases de Visual Basic de las clases Public de objetos COM, incluso si se crearon en versiones anteriores de Visual Basic. Las propiedades y mtodos de las clases heredadas de objetos COM pueden ser invalidados o sobrecargados del mismo modo que las propiedades y mtodos de cualquier otra clase base. La herencia de objetos COM resulta til cuando se tiene una biblioteca de clases que no se desea volver a compilar. En el procedimiento siguiente se muestra cmo usar Visual Basic 6.0 para crear un objeto COM que contiene una clase y, a continuacin, utilizar ste como clase base.

Nota:

Es posible que su equipo muestre nombres o ubicaciones diferentes para algunos de los elementos de la interfaz de usuario de Visual Studio incluidos en las instrucciones siguientes. La edicin de Visual Studio que se tenga y la configuracin que se utilice determinan estos elementos. Para obtener ms informacin, vea Valores de configuracin de Visual Studio.

Para generar el objeto COM que se utiliza en este tutorial


1. 2. En Visual Basic 6.0, abra un proyecto de archivo DLL ActiveX nuevo. Se crea un proyecto denominado Project1. Tiene una clase denominada Class1. En el Explorador de proyectos, haga clic con el botn secundario del mouse (ratn) en Project1 y, a continuacin, haga clic en Propiedades de Project1. Aparece el cuadro de dilogo Propiedades del proyecto. En la ficha General del cuadro de dilogo Propiedades del proyecto, escriba ComObject1 en el campo Nombre de proyecto para cambiar el nombre del proyecto. En el Explorador de proyectos, haga clic con el botn secundario del mouse en Class1 y, a continuacin, haga clic en Propiedades. Aparecer la ventana Propiedades correspondiente a la clase. Establezca la propiedad Name en MathFunctions. En el Explorador de proyectos, haga clic con el botn secundario del mouse en MathFunctions y, a continuacin, haga clic en Ver cdigo. Aparece el Editor de cdigo. Agregue una variable local, que contendr el valor de la propiedad:

3. 4.

5. 6. 7.

Copiar ' Local variable to hold property value Private mvarProp1 As Integer
8. Agregue los procedimientos de propiedad Let y Get:

Copiar Public Property Let Prop1(ByVal vData As Integer) 'Used when assigning a value to the property. mvarProp1 = vData End Property Public Property Get Prop1() As Integer 'Used when retrieving a property's value. Prop1 = mvarProp1 End Property

9.

Agregue una funcin:

Copiar Function AddNumbers( _ ByVal SomeNumber As Integer, _ ByVal AnotherNumber As Integer) _ As Integer

AddNumbers = SomeNumber + AnotherNumber End Function


10. Cree y registre el objeto COM; para ello, haga clic en Crear ComObject1.dll en el men Archivo.

Nota:
Aunque es posible exponer una clase creada con Visual Basic como un objeto COM, en realidad, no se trata de un verdadero objeto COM y no se puede utilizar en este tutorial. Para obtener informacin detallada, vea Interoperabilidad COM en aplicaciones .NET Framework.

Ensamblados de interoperabilidad

En el procedimiento siguiente va a crear un ensamblado de interoperabilidad que servir como puente entre el cdigo no administrado (como un objeto COM) y el cdigo administrado que utiliza Visual Studio. El ensamblado de interoperabilidad creado por Visual Basic controla muchos de los aspectos del trabajo con objetos COM, como el clculo de referencias de interoperabilidad, el proceso de empaquetado de parmetros y valores devueltos en los tipos de datos equivalentes enviados a objetos COM (o recibidos de objetos COM). La referencia de la aplicacin de Visual Basic apunta al ensamblado de interoperabilidad, no al objeto COM real.

Para utilizar un objeto COM con Visual Basic 2005 y versiones posteriores
1. 2. Abra un nuevo proyecto de aplicacin para Windows de Visual Basic. En el men Proyecto, haga clic en Agregar referencia. Aparece el cuadro de dilogo Agregar referencia. 3. En la ficha COM, haga doble clic en ComObject1 en la lista Nombre de componente y, a continuacin, haga clic en Aceptar.

4.

En el men Proyecto, haga clic en Agregar nuevo elemento. Se abrir el cuadro de dilogo Agregar nuevo elemento.

5.

En el panel Plantillas, haga clic en Clase. En el campo Nombre aparecer el nombre de archivo predeterminado, Class1.vb. Cambie este campo a MathClass.vb y haga clic en Agregar. Esto crear una clase denominada MathClass y mostrar su cdigo.

6.

Agregue el cdigo siguiente al principio de MathClass para heredar de la clase COM.

VB C# C++ F# JScript

Copiar ' The inherited class is called MathFunctions in the base class, ' but the interop assembly appends the word Class to the name. Inherits ComObject1.MathFunctionsClass

7.

Sobrecargue el mtodo pblico de la clase base agregando el cdigo siguiente a MathClass:

VB C# C++ F# JScript

Copiar ' This method overloads the method AddNumbers from the base class.

Overloads Function AddNumbers( _ ByVal SomeNumber As Integer, _ ByVal AnotherNumber As Integer) _ As Integer

Return SomeNumber + AnotherNumber End Function

8.

Ample la clase heredada agregando el cdigo siguiente a MathClass:

VB C# C++ F# JScript

Copiar ' The following function extends the inherited class.

Function SubtractNumbers( _ ByVal SomeNumber As Integer, _ ByVal AnotherNumber As Integer) _ As Integer

Return AnotherNumber - SomeNumber End Function

La nueva clase hereda las propiedades de la clase base del objeto COM, sobrecarga un mtodo y define otro mtodo para extender la clase.

Para probar la clase heredada

1. 2.

Agregue un botn al formulario de inicio y, a continuacin, haga doble clic en l para ver su cdigo. En el procedimiento del controlador de eventos Click del botn, agregue el cdigo siguiente para crear una instancia de MathClass y llamar a los mtodos sobrecargados:

VB C# C++ F# JScript

Copiar Dim Result1 As Short Dim Result2 As Integer Dim Result3 As Integer Dim MathObject As New MathClass Result1 = MathObject.AddNumbers(4S, 2S) ' Add two Shorts. Result2 = MathObject.AddNumbers(4, 2) 'Add two Integers. Result3 = MathObject.SubtractNumbers(2, 4) ' Subtract 2 from 4. MathObject.Prop1 = 6 ' Set an inherited property.

MsgBox("Calling the AddNumbers method in the base class " & _

"using Short type numbers 4 and 2 = " & Result1) MsgBox("Calling the overloaded AddNumbers method using " & _ "Integer type numbers 4 and 2 = " & Result2) MsgBox("Calling the SubtractNumbers method " & _ "subtracting 2 from 4 = " & Result3) MsgBox("The value of the inherited property is " & _ MathObject.Prop1)

3.

Presione F5 para ejecutar el proyecto.

Cuando haga clic en el botn del formulario, se llamar primero al mtodo AddNumbers con nmeros de tipo de datos Short y Visual Basic elegir el mtodo apropiado en la clase base. La segunda llamada a AddNumbers se dirige al mtodo de sobrecarga de MathClass. La tercera llamada llama al mtodo SubtractNumbers, que extiende la clase. Se establece el valor de la propiedad en la clase base y se muestra dicho valor.

Pasos siguientes

Es posible que haya observado que la funcin AddNumbers sobrecargada parece tener el mismo tipo de datos que el mtodo heredado de la clase base del objeto COM. Esto se debe a que los argumentos y parmetros del mtodo de la clase base estn definidos como enteros de 16 bits en Visual Basic 6.0, pero se exponen como enteros de 16 bits de tipo Short en las versiones posteriores de Visual Basic. La nueva funcin acepta enteros de 32 bits y sobrecarga la funcin de la clase base. Al trabajar con objetos COM, es importante comprobar el tamao y los tipos de datos de los parmetros. Por ejemplo, al utilizar un objeto COM que acepta un objeto de coleccin de Visual Basic 6.0 como argumento, no puede proporcionar una coleccin de una versin posterior de Visual Basic. Para obtener ms informacin sobre los controles de tipo de datos, vea Cambios en el lenguaje para usuarios de Visual Basic 6.0. Es posible reemplazar propiedades y mtodos heredados de clases COM, lo que significa que se puede declarar una propiedad o mtodo local que reemplace una propiedad o mtodo heredado de una clase base COM. Las reglas para reemplazar propiedades COM heredadas son similares a las reglas para reemplazar otras propiedades y mtodos, con las excepciones siguientes:

Si reemplaza cualquier propiedad o mtodo heredado de una clase COM, deber reemplazar todas las dems propiedades y mtodos heredados. No es posible reemplazar las propiedades que utilizan parmetros ByRef.

La herencia y la clase de objeto base


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Casi todas las tareas que se pueden realizar con Visual Basic implican el uso de objetos, entre ellos algunas entidades que normalmente no se suponen objetos, por ejemplo, cadenas y enteros. Todos los objetos de Visual Basic se derivan y heredan mtodos de una clase base llamada System.Object. La clase System.Object proporciona una clase base comn para todos los objetos de .NET Framework, lo que garantiza la interoperabilidad de objetos desarrollada con Visual Studio. Las nuevas clases heredan implcitamente la clase System.Object; no es necesario incluir explcitamente esta clase con una instruccin Inherits. De los mtodos que los objetos heredan de System.Object, uno de los ms tiles es GetType, que se utiliza para devolver el tipo exacto del objeto actual.

Cmo funcionan los mtodos New y Finalize en una jerarqua de clases


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Cuando se crea una instancia de una clase, Common Language Runtime (CLR) intenta ejecutar un procedimiento denominado New, si existe en ese objeto. New es un tipo de procedimiento llamado constructor que se utiliza para inicializar nuevos objetos antes de que se ejecute cualquier otro cdigo de un objeto. Un constructor New puede utilizarse para abrir archivos, conectarse a bases de datos, inicializar variables y realizar cualquier otra tarea necesaria antes de poder utilizar un objeto.

Cuando se crea una instancia de una clase derivada, se ejecuta primero el constructor Sub New de la clase base, seguido de los constructores de las clases derivadas. Esto se debe a que la primera lnea de cdigo en un constructor Sub New utiliza la sintaxis MyBase.New() para llamar al constructor de la clase situada inmediatamente por encima en la jerarqua de clases. Despus se llama al constructor Sub New para cada clase de la jerarqua hasta llegar al constructor de la clase base. En este punto, se ejecuta el cdigo del constructor para la clase base, seguido del cdigo en cada constructor de todas las clases derivadas, ejecutndose en ltimo lugar el cdigo de las clases ms derivadas.

Cuando un objeto deja de ser necesario, CLR llama al mtodo Finalize para ese objeto antes de liberar su memoria. El mtodo Finalize se denomina destructor porque realiza tareas de limpieza, como guardar informacin de estado, cerrar archivos y conexiones a bases de datos, y otras tareas que deben realizarse antes de liberar el objeto.

Polimorfismo
Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 El polimorfismo se refiere a la posibilidad de definir mltiples clases con funcionalidad diferente, pero con mtodos o propiedades denominados de forma idntica, que pueden utilizarse de manera intercambiable mediante cdigo cliente en tiempo de ejecucin.

Cmo proporciona Visual Basic polimorfismo


Visual Studio 2008 Otras versiones

Actualizacin: noviembre 2007 Tradicionalmente, el polimorfismo en Visual Basic se realizaba mediante interfaces, y stas an pueden usarse para este propsito. Sin embargo, ahora, Visual Basic proporciona la opcin de usar la herencia para conseguir el polimorfismo. Como en otros temas de la programacin orientada a objetos, la opcin que debe utilizarse depende de los requisitos especficos. En general, use la herencia cuando desee crear funcionalidad bsica que las clases derivadas puedan extender; use interfaces cuando varias implementaciones diferentes deban proporcionar

Вам также может понравиться