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

En este artculo podemos ver los conceptos bsicos de la OOP (Object Oriented Programming) y su implementacin en VB.

NET, incluyendo algunas de sus particulares detalles de implementacin como la palabra clave Shadows. Cuidado con lo que deseas porque se te puede conceder! Esto reza un viejo dicho, y no puede ser ms aplicable a la comunidad de desarrolladores Visual Basic. Uno de esos deseos fue tener herencia, sin ningn tipo de limitaciones, cosa que si bien es muy deseable en ciertos contextos tambin es cierto que mal usada puede traer muchos dolores de cabeza. Pero tampoco vamos a ser alarmistas y pensar que la herencia es algo TAN complejo que solo unos pocos pueden comprender y menos usar en la realidad, nada est mas lejos de la verdad. Obviamente para poder usar de forma efectiva la herencia es muy importante entender en que casos es buena y nos puede aportar algo positivo, y cuando es mejor usar otras tcnicas de programacin ya conocidas como las interfaces. Y ya que estamos con los dichos, yo resumira el uso de la herencia para los desarrolladores Visual Basic con uno muy escuchado en estos ltimos tiempos: No tenga miedo, tenga cuidado. Visual Basic ha evolucionado mucho desde sus inicios hace ms de 10 aos, y uno de sus hitos ms importantes fue la versin 4.0 con un nuevo paradigma de desarrollo: orientacin a objetos (o casi). De hecho, VB4 cumpla con todos los criterios de un lenguaje orientado a objetos salvo uno: herencia, y esto se ha mantenido as hasta el da de hoy. Visual Basic.NET completa el requisito faltante (y agrega algunos otros ms como mtodos constructores, sobrecarga de mtodos, el modificador Protected y la posibilidad de reemplazar mtodos compilados con Override, por ejemplo). Tambin incluye la nueva y misteriosa palabra clave Shadows, que no est presente en otros lenguajes. A primera vista puede ser difcil de entender la diferencia entre las palabras clave Override y Shadows, y darse cuenta de la necesidad de esta ltima. Incluso podra llegar a cuestionarse la salud mental de los integrantes del equipo de desarrollo de Visual Basic .NET, en que estaban pensando?, eh?. Bueno, a continuacin veremos que (por suerte) esto no es as y exploraremos los pormenores de las palabras clave Override, Overloads

y Shadows e intentaremos aclarar la confusin. Conceptos de Herencia Si bien estos conceptos no son nada nuevos y son conocidos por muchas personas, vamos a repasarlos un poco mientras creamos nuestro proyecto de prueba para explorar el uso de Overloads, Override y Shadows. La herencia nos permite crear una nueva clase que automticamente tenga el comportamiento y mtodos de otra existente. De alguna manera es como si estuviramos fusionando el cdigo de la vieja clase con el de la nueva, pero sin tener que volver a escribirlo (o copy/paste). Bueno, manos a la obra. Abramos nuestro Visual Studio.NET y creemos un nuevo proyecto de tipo Console Application que se llame HerenciaVB. Para probar los conceptos de herencia vamos a crear una nueva clase base (base class) y una subclase. La clase base tendr cierta funcionalidad que representa a una entidad de la vida real, por ejemplo un Video. La subclase se derivar de esta clase base por lo que ser tambin un Video, pero una de un tipo mas especializado. De esto se trata la herencia, crear nuevas clases que tienen toda la funcionalidad de una clase base pero son ms especializadas o con un foco mas restringido que la original. Manos a la Obra Haciendo clic derecho sobre el tem del proyecto en la ventana Solution Explorer y seleccionando la opcin Add Add Class, agreguemos una nueva clase llamada Video. Esta clase contendr la funcionalidad bsica para representar prcticamente cualquier clase de video, que la podemos implementar con el siguiente cdigo: Public Class Video Private strID As String Private strTitulo As String Private sngPrecio As Single Public Property ID() As String

Get Return strID End Get Set(ByVal Value As String) strID = Value End Set End Property

Public Property Titulo() As String Get Return strTitulo End Get Set(ByVal Value As String) strTitulo = Value End Set End Property

Public Property Precio() As Single Get Return sngPrecio End Get Set(ByVal Value As Single) sngPrecio = Value

End Set End Property End Class Con esto tenemos nuestro video base que posee un ID (quizs el nmero de serie del fabricante), ttulo y precio, cosas que todos los videos tienen en comn. Comienza la Herencia Ahora, usando nuestra clase de video genrica podemos construir una mas especializada, por ejemplo un DVD. Agreguemos una nueva clase que se llame DVD igual como hicimos con la anterior, usando la opcin Add Class del men del proyecto. Un DVD incluye la misma funcionalidad que un Video de nuestra clase base, as que lo que vamos a hacer es simplemente heredar de la clase Video escribiendo lo siguiente: Public Class DVD Inherits Video End Class Con este pequeo cambio nuestra nueva clase DVD ya tiene un ID, Ttulo y Precio, propiedades que estn implementadas en la clase base Video. Sin embargo, un DVD puede tener otras propiedades y comportamiento que un Video estndar, como por ejemplo si tiene mltiples pistas de audio. Para ilustrar nuestro punto vamos a implementar este cambio, de los muchos posibles: Public Class DVD Inherits Book Private bMultiplesPistas As Boolean Public Property MultiplesPistas() As Boolean Get

Return bMultiplesPistas End Get Set(ByVal Value As Boolean) bMultiplesPistas = Value End Set End Property End Class

La clase Video contina teniendo tres propiedades, pero nuestra nueva clase DVD ahora tiene cuatro (las tres de la clase Video y la nueva MultiplesPistas que agregamos). Probando Vamos a ver como funciona esto escribiendo el siguiente cdigo en el Module1 que est en el proyecto: Module Module1 Sub Main() Dim basicVideo As New Video() With basicVideo .ID = "12345" .Titulo = "Video Bsico" .Precio = 15 End With

Dim dvdVideo As New DVD()

With dvdVideo .ID = "54321" .Titulo = "Spiderman" .Precio = 7 .MultiplesPistas = true End With

Console.WriteLine("Video Bsico") With basicVideo Console.WriteLine(" ID: {0}", .ID) Console.WriteLine(" Ttulo: {0}", .Titulo) Console.WriteLine(" Precio: {0}", .Precio) End With

Console.WriteLine("DVD") With dvdVideo Console.WriteLine(" ID: {0}", .ID) Console.WriteLine(" Ttulo: {0}", .Titulo) Console.WriteLine(" Precio: {0}", .Precio) Console.WriteLine(" Mltiples Pistas: {0}", .MultiplesPistas) End With

Console.Read()

End Sub End Module Este cdigo simplemente muestra como pueden ser usadas las clases Video y DVD, y confirma que nuestra clase DVD en verdad ha heredado los mtodos de la clase Video. Primero creamos y cargamos con datos un objeto de tipo Video, y luego hacemos lo propio con la clase DVD, haciendo uso de los mtodos heredados. Por ltimo usamos el mtodo Console.WriteLine para volcar los valores contenidos en las propiedades de ambos objetos y la lnea Console.ReadLine se encarga de esperar a que se pulse una tecla antes de finalizar la ejecucin del programa (algo muy til cuando se est corriendo un programa desde el entorno de desarrollo). Lo que hemos hecho hasta ahora es muy simple, heredamos de una clase base y la extendimos agregando un nuevo comportamiento. En muchos casos esto no es suficiente, ya que a menudo necesitamos no solo agregar nueva funcionalidad sino modificar o reemplazar por completo alguna ya existente en la clase base, y aqu en donde entran en juego los Overloads, Override y Shadows. Sobrecarga de Mtodos (Overload) La sobrecarga de mtodos nos permite que una clase tenga ms de un mtodo con el mismo nombre, siempre y cuando todos los mtodos tengan diferentes parmetros. Lo que importa no es el nombre de los parmetros sino su tipo de dato, as como su cantidad. El conjunto de los tipos de dato de los parmetros de un mtodo es lo que se conoce como firma del mtodo (method signature). En realidad, hasta ahora la sobrecarga de mtodos no tiene nada que ver con la herencia, pero estos dos conceptos pueden interactuar de formas muy interesantes. Bueno, vamos a ver como funciona la sobrecarga de mtodos en el contexto de una nica clase. Volvamos al cdigo de nuestra clase Video y agreguemos lo siguiente: Private intItemsComprados As Integer Public ReadOnly Property ItemsComprados() As Integer Get

Return intItemsComprados End Get End Property

Public Sub Comprar() intItemsComprados += 1 End Sub Este cdigo simplemente agrega una nueva propiedad y un mtodo a nuestra clase base. El mtodo agregado nos permite especificar que hemos comprado una nueva copia de nuestro Video, pero es un poco limitante ya que solamente podemos comprar de a uno por vez. Para remediar esta situacin podemos agregar otra versin del mismo mtodo que reciba un parmetro indicando cuantas copias deseamos comprar: Public Sub Comprar(ByVal Cantidad As Integer) intItemsComprados += Cantidad End Sub Ahora tenemos dos implementaciones diferentes del mtodo Comprar en nuestra clase y ambas tienen diferentes firmas (cantidad y tipo de parmetros) y por eso se nos permite que ambos mtodos tengan el mismo nombre. Si volvemos a nuestro cdigo de prueba podemos modificarlo para reflejar estos cambios introducidos: With basicVideo .ID = "12345" .Titulo = "Video Bsico" .Precio = 15 .Comprar()

.Comprar(8) End With Cuando se ejecuta el mtodo Comprar sin parmetros se est invocando la primera implementacin que suma uno a la cantidad comprada hasta el momento, la segunda invocacin agregar la cantidad de 8 al total comprado hasta el momento ejecutando la segunda implementacin de nuestro mtodo. With basicVideo Console.WriteLine(" ID: {0}", .ID) Console.WriteLine(" Ttulo: {0}", .Titulo) Console.WriteLine(" Precio: {0}", .Precio) Console.WriteLine(" tems Comprados: {0}", .ItemsComprados) End With Con esto mostramos como funciona la sobrecarga de mtodos en una clase nica, ahora vamos a ver como podemos aprovechar esto usando herencia. Sobrecarga de Mtodos en una Subclase Recordemos que nuestra clase DVD hereda ambas implementaciones de nuestro mtodo Comprar, pero ahora necesitamos agregar otra versin de este mtodo para tener en cuenta que el precio del producto puede variar segn un descuento especial del cliente. Vayamos al cdigo de la clase DVD y agreguemos lo siguiente: Public Overloads Sub Comprar(ByVal Descuento As Single) Precio = Precio - Descuento MyBase.Comprar() End Sub Esto se empieza a poner interesante. Lo que primero podemos ver es que el mtodo incluye la palabra Overloads. Esto es obligatorio para

cualquier mtodo de una subclase que hace una sobrecarga de un mtodo de una clase base. Podemos no incluir esta palabra clave en la definicin del mtodo, pero en ese caso se asume el uso de Shadows, cuya funcin veremos mas adelante. Por el momento es importante saber que ambas opciones nos van a provocar cambios radicales de comportamiento en nuestra subclase. Recordemos que para poder hacer una sobrecarga de un mtodo es necesario que tengan diferente firma de parmetros. Si esto no es as, no ser posible realizar la sobrecarga. Por ltimo, observemos la lnea que usa la palabra clave MyBase: MyBase.Comprar() Esta lnea de cdigo ejecuta el mtodo Comprar que est implementado en la clase base. La palabra MyBase es reservada del lenguaje y siempre representa a la clase base dentro de una subclase, y puede utilizarse en cualquier parte de la subclase para invocar mtodos de la clase base ignorando la implementacin propia de la subclase. Para ver como funciona este nuevo mtodo podemos modificar el cdigo del Module1 para ver el resultado: With dvdVideo .ID = "54321" .Titulo = "Spiderman" .Precio = 7 .MultiplesPistas = true .Comprar(2.0!) End With Al hacer esto, automticamente estamos realizando una compra y a la vez modificando el precio de venta. Al mostrar el resultado de nuestra operacin podemos confirmar que el precio de compra ha sido modificado. Hasta ahora pudimos ver como podemos extender una clase base con nuevos mtodos que hacen sobrecarga de mtodos existentes en la clase base y que se implementan totalmente en la subclase. Sin

embargo, algunas veces es necesario alterar o reemplazar por completo la funcionalidad de un mtodo de la clase base y no agregar nuevas implementaciones. Para poder hacer esto necesitamos usar Override o Shadows, como veremos a continuacin. Reemplazando Mtodos con Override El diseador de una clase base es responsable de pensar por adelantado los posibles usos que otros desarrolladores puedan darle usando herencia. En particular, el diseador de una clase debe decidir si un mtodo en particular puede ser alterado, reemplazado o nada de esto. Si no se especifica lo contrario, los mtodos no pueden ser alterados o reemplazados utilizando Override. Los mtodos siempre pueden reemplazarse utilizando Shadows, lo que veremos con mas detalle mas tarde, pero la forma preferida de alterar o reemplazar un mtodo base es utilizando Override ya que lo estamos haciendo con el permiso (y conocimiento) del autor de la clase original. Para especificar que un mtodo puede ser alterado o reemplazado utilizando Override debemos marcarlo con el modificador Overridable. Por ejemplo, si el autor de la clase base Video prev que en el futuro podra ser necesario implementar un sistema de precios distinto al actual, podra marcar la propiedad Precio con Overridable para permitir explcitamente este comportamiento: Public Overridable Property Precio() As Single Get Return sngPrecio End Get Set(ByVal Value As Single) sngPrecio = Value End Set End Property Esta modificacin no implica ningn cambio de funcionalidad en las clases Video o DVD, pero significa que la subclase DVD puede

implementar su propia versin de la propiedad Precio si es necesario. Por ejemplo, podramos modificar (aumentar, obviamente) el precio de un DVD si este tiene mltiples pistas de audio, y sera de esta manera: Public Overrides Property Precio() As Single Get If MultiplesPistas Then Return MyBase.Precio* 2 Else Return MyBase.Precio End If End Get Set(ByVal Value As Single) MyBase.Precio = Value End Set End Property Acurdense que es necesario declarar el mtodo como Overridable para poder reemplazarlo con Override. Si no usamos Override el nuevo mtodo usar Shadows sobre el mtodo original. En la implementacin nueva de la propiedad Precio podemos ver que no hemos reemplazado completamente la funcionalidad original sino que se ha alterado. El cdigo nuevo hace uso de la palabra clave MyBase para ejecutar el mtodo de la clase base y aprovechar el cdigo existente, de hecho, el almacenamiento del valor se hace por completo en la clase base (no hay variable privada que corresponda a la propiedad y almacene su valor). Set(ByVal Value As Single) MyBase.Precio = Value End Set

Aqu no estamos modificando funcionalidad para nada, de hecho estamos delegando totalmente la llamada a la base clase. Solamente se est modificando el comportamiento de la clase base al momento de obtener el valor de la propiedad Precio. EL cdigo ahora verifica si el DVD tiene mltiples pistas de audio y si esto es as multiplica el precio por dos (oferta). Hasta aqu pudimos ver como usar Overrides para alterar el comportamiento de una clase base. Si hubiramos querido reemplazar completamente el mtodo sera necesario evitar la llamada a la clase base (MyBase) y proveer la funcionalidad de almacenamiento interno del valor que estamos necesitando. Hay que tener cuidado y hacer muchas pruebas antes de reemplazar totalmente un mtodo ya que esto puede tener consecuencias indeseadas en el comportamiento de la subclase. Es muy posible que este mtodo interacte con otros de la clase base y obviamente las cosas no van a funcionar como esperamos. Mucha de la responsabilidad de asegurarse que el funcionamiento de un mtodo marcado con Overridable es del diseador de la clase base. De ser as, debe asumirse que alguna subclase reemplazar totalmente un mtodo y entonces la clase base debe disearse teniendo esto en cuenta. Ejecutando los nuevos Mtodos El concepto de alterar o reemplazar con Override un mtodo es bastante simple. El diseador de la clase decide cuales mtodos puede ser alterados o reemplazados y permite a los diseadores de las subclases el utilizar esta funcionalidad. Las cosas se complican un poco cuando queremos ejecutar alguno de estos mtodos alterados en una subclase. Antes de que nos podamos dar cuenta del porque esto es complicado necesitamos entender que existe una enorme diferencia entre el tipo de una Variable y el tipo de un Objeto. Tpicamente declaramos las variables que usamos del mismo tipo que el objeto que representan, por ejemplo: Dim myDVD As New DVD() Esta variable es de tipo DVD, y el objeto al que apunta la variable es de tipo DVD. Para aclarar un poco las cosas, la lnea de arriba se puede escribir como:

Dim myDVD As DVD = New DVD() Cuando usamos herencia podemos elegir declarar nuestra variable como del tipo de la clase base en lugar del objeto real a utilizar. Esto es muy til ya que podemos escribir cdigo genrico que funcione sin importarnos el tipo real del objeto que estamos manipulando (esta es una de las caractersticas de la programacin OO que se conoce como Polimorfismo). Esto funciona porque todas las subclases que deriven de Video tienen las mismas propiedades bsicas como ID, Titulo y Precio. Para hacer esto podemos declarar nuestra variable para que sea del tipo Video, pero an as contendr a un objeto de tipo DVD. Dim myVideo As Video = New DVD() Mientras que el objeto es realmente un DVD, nosotros lo vemos como un Video porque la variable que lo contiene ha sido declarada con este tipo, y solamente podemos acceder las propiedades y mtodos de un objeto Video. Agreguemos el siguiente cdigo a nuestro Module1: Dim myVideo As Video = New DVD() With myVideo .ID = "54321" .Titulo = "Robocop III" .Precio = 7 End With CType(myVideo, DVD).MultiplesPistas = True CType(myVideo, DVD).Comprar(2.0!) Este cdigo carga los valores de las propiedades ID, Titulo y Precio. Hasta aqu no hay sorpresas ya que estos mtodos son parte de la clase base. Estas lneas de cdigo van a funcionar bien con cualquier objeto de tipo Video o que derive del mismo. El Polimorfismo es la capacidad de utilizar el mismo cdigo con objetos de diferente tipo, y es algo muy til.

Las ltimas dos lneas son mas intrigantes porque estamos usando la funcin CType() para poder ver temporalmente a la variable myVideo como de tipo DVD, y as poder ver la propiedad MultiplesPistas y ejecutarle el mtodo sobrecargado Comprar que recibe un parmetro de tipo Single. Obviamente estas lneas solamente funcionan si el objeto es realmente del tipo DVD (o uno derivado de este), de otra manera la conversin fallara. Entonces, Qu pasa con el mtodo Precio que alteramos? Aqu la pregunta realmente es Qu implementacin de este mtodo se va a invocar si nuestra variable es del tipo Video y nuestro objeto es del tipo DVD? Para ver la respuesta escribamos el siguiente cdigo a continuacin del que agregamos antes: Console.WriteLine("myVideo") With myVideo Console.WriteLine(" ID: {0}", .ID) Console.WriteLine(" Ttulo: {0}", .Titulo) Console.WriteLine(" Precio: {0}", .Precio) Console.WriteLine(" tems Comprados: {0}", .ItemsComprados) End With Si ejecutamos el cdigo vamos a ver que el precio de nuestro video es 5 y no 7. Esto quiere decir que se ejecut la implementacin del objeto DVD! Cuando un mtodo es marcado con Overridable se convierte en un mtodo virtual. Esto significa que sin importar el tipo de la variable que usemos siempre se va a ejecutar la implementacin que dicta el tipo del objeto. Para aclarar un poco las cosas veamos que ocurre con las diferentes combinaciones posibles entre tipos de objetos y variables: Esto es muy importante ya que podemos estar seguros de que al escribir cdigo genrico como el mostrado ms arriba an se ejecutan los mtodos especializados en las subclases, cosa que generalmente es lo deseado. Esto ltimo nos da el pi para discutir el comportamiento al usar

Shadows y poder explicar el comportamiento diferente que posee. Shadows y ms Shadows Hasta aqu vimos que podemos extender una clase base agregndole nuevos mtodos. Tambin hemos visto que podemos agregar nuevas versiones de mtodos existentes utilizando sobrecarga (Overloads) y tambin que es posible alterar o reemplazar totalmente un mtodo contando con el visto bueno del diseador de la clase usando Override. Ahora bien, que sucede cuando necesitamos alterar o reemplazar un mtodo existente y la clase base no nos da el permiso para hacerlo? Si el mtodo no est marcado con Overridable no nos es posible alterarlo o reemplazarlo. Probablemente esto sea una premisa de diseo y es obvio que el diseador explcitamente no ha considerado la posibilidad de que una subclase pueda alterar o reemplazar el mtodo en cuestin, as que es necesario pensarlo cuidadosamente y evaluar las consecuencias de ignorar una premisa de diseo de la base clase. An as, hay casos en lo que es necesario hacerlo sin importar las intenciones del diseador original de la clase, o simplemente es diseo no es el correcto o adecuado para nuestras necesidades. Otro escenario posible podra ser el de tener una aplicacin versin 1.0 que hereda y extiende una clase base. Luego, la versin 2.0 de la clase base agrega un nuevo mtodo que entra en conflicto con el nuevo mtodo que nosotros agregamos en nuestra subclase. En vez de cambiar el nombre del mtodo en nuestra subclase para evitar el conflicto, y rescribir el cdigo que usa nuestra clase derivada, podemos simplemente elegir ignorar el nuevo mtodo de la clase base y continuar utilizando en que existe en la subclase. En ambos casos podemos usar el modificador Shadows para lograr nuestro objetivo reemplazando por completo el mtodo de la clase base. Creo que la mejor forma de evaluar la funcionalidad y utilidad de esta posibilidad es a travs de compararlo con lo que aprendimos de los otros modificadores Overloads y Override. La sobrecarga de un mtodo permite agregar una nueva variacin de un mtodo existente siempre y cuando el nuevo mtodo tenga una firma diferente. El uso de Shadows completamente reemplaza al mtodo y todas sus variantes de la clase base, dejando a la subclase con una nica versin del mtodo reemplazado (el que acabamos de crear). Usando este modificador no estamos extendiendo una interfaz, sino que estamos reemplazando totalmente un mtodo existente y sus variantes.

A diferencia de usar Override, Shadows permite reemplazar un mtodo de la clase base sin el visto bueno del diseador, lo que trae aparejado un riesgo importante y adems requiere la realizacin de profundas pruebas para asegurarnos de que todo funciona como esperamos. Hay que tener en cuenta que la clase base nunca fue pensada para hacer esto que nosotros vamos a hacer ahora. Por otra parte, el uso de Shadows tiene un importante efecto secundario. Como dijimos antes el uso de Override genera mtodos virtuales lo que significa que la implementacin del mtodo alterado o reemplazado que va a ser invocado depende del tipo del objeto que estamos usando y no del tipo de la variable que lo referencia. Cuando un mtodo es reemplazado con Shadows no es virtual y entonces es el tipo de la variable el que dicta cual implementacin del mtodo ser invocada. El tipo del objeto que referencia la variable es completamente ignorado. Algunas Comparaciones Prcticas Podemos apreciar las diferencias concretas de usar Overloads y Shadows modificando ligeramente el mtodo Comprar de la subclase DVD para que use el segundo en lugar del primero: Public Shadows Sub Comprar(ByVal Descuento As Single) Precio = Precio - Descuento MyBase.Comprar() End Sub El modificador Overloads ha sido reemplazado por Shadows, aunque a decir verdad este modificador no es tcnicamente necesario ya que el comportamiento de Shadows es el que se aplica si no se especifica otro. An as es deseable incluirlo ya que de lo contrario recibiremos una advertencia del compilador especificando que el mtodo est siendo reemplazado con Shadows en lugar de Override, y estamos explcitamente definiendo que este es el comportamiento buscado y no un error de tipeo. Si ejecutamos nuestro nuevo cdigo vemos que la utilizacin de MyBase an funciona de la forma esperada. Tpicamente, usaremos MyBase junto con Shadows teniendo en cuenta que el diseo de la clase base puede no soportar el que reemplacemos totalmente un mtodo, y con el

objetivo de aliviar los problemas que puedan surgir al eliminar por completo el cdigo del mtodo original y sus variaciones. Porqu decimos eliminar por completo el mtodo original? Porque esto es exactamente lo que ocurre en nuestra subclase. Hasta ahora podramos haber escrito cdigo como el siguiente: Dim myDVD As New DVD() With myDVD .Comprar() .Comprar(5) .Comprar(2.0!) End With La clase DVD poda hacer uso de las dos implementaciones del mtodo Comprar de su clase base usando herencia, adems del nuevo que agregamos luego a nuestra subclase usando sobrecarga de mtodos. Ahora, al usar Shadows los mtodos originales no existen ms y solamente podemos utilizar el nuevo mtodo que creamos para nuestra subclase. Las invocaciones a los mtodos Comprar() y Comprar(5) no funcionan ms, solamente Comprar(2.0!). Shadows vs. Overrides Para ver la diferencia de comportamiento entre estos dos modificadores de mtodos vamos a modificar la implementacin de la propiedad Precio de la clase DVD de la siguiente forma: Public Shadows Property Precio() As Single Get If MultiplesPistas Then Return MyBase.Precio* 2 Else Return MyBase.Precio

End If End Get Set(ByVal Value As Single) MyBase.Precio = Value End Set End Property Hemos reemplazado el Overrides por Shadows como dijimos anteriormente, y al ejecutar el nuevo cdigo podemos ver que el precio de nuestra variable myVideo es 12 y no 24 como en el caso anterior. Lo que ha pasado aqu es que el cdigo modificado de la propiedad Precio no se ha ejecutado, en su lugar se ha ejecutado el cdigo original de la clase base que no contemplaba el aumento de precio de los DVDs. Como podemos ver este es el comportamiento opuesto al de los mtodos virtuales que se logra con Overrides, quiere decir que se ha ejecutado el mtodo que corresponde al tipo de la variable y no el del objeto que la misma referencia. Para dejar bien en claro el comportamiento de Shadows podemos consultar la siguiente tabla:

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