Sei sulla pagina 1di 8

Objetos Herencia y Polimorfismo

Mucho se dice sobre los objetos y la herencia, la verdad es que este concepto es uno de los pilares para la reutilizacin de componentes. En la exposicin terica es fcil decir que existe una clase base de la cul otras se "derivan" formando una jerarqua de clases. Formalmente debemos decir que esa clase base es una Generalizacin de las otras clases (esto es cuando vamos desde abajo hacia arriba ) y tambin decimos que las otras clase son una Especializacin de la clase base (es cuando vamos desde arriba hacia abajo). El siguiente esquema muestra el diagrama de clases que representa una simple relacin de mascotas:

No hace falta mucha explicacin, se trata de una clase que define a una mascota cualquiera y luego tenernos las especializaciones para Gato, Pato y Perro. Hay que observar que cuando de una mascota se trata nosotros (los humanos) acostumbramos a ponerle un nombre; pues bien no importa de qu mascota se trate siempre tiene nombre, eso es un atributo de la clase base (Mascota). Despus de un tiempo le enseamos a nuestra mascota a presentarse, y en este caso vamos a representar que cada mascota se puede presentar diciendo su nombre que tipo de mascota es y el ruido que normalmente hace. En esta situacin es que se observa que como todas las mascotas tienen un nombre es posible poner el cdigo para mostrar el nombre en la clase base y el cdigo para el ruido que cada mascota realiza en cada una de las clases, por esa razn es que el mtodo Presentarse figura en la clase base (superclase) y en las clases derivadas (subclases). Veamos el cdigo de Mascota.cs
1: using System;

Objetos Herencia y Polimorfismo


2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45:

namespace Herencia1 { /// <summary> /// Clase base /// </summary> public class Mascota { /// <summary> /// Constructor por defecto /// </summary> public Mascota() { } /// <summary> /// Constructor especializado que fija el nombre de la mascota /// </summary> /// <param name="nombre">Nombre de la mascato</param> public Mascota(string nombre) { Nombre = nombre; } /// <summary> /// Mantiene el nombre de la mastaco /// </summary> private string nombre = string.Empty; /// <summary> /// Propiedad para acceder al nombre de la mascota /// No permite la asignacin de nombre nulos (operador ??) /// </summary> public string Nombre { get { return nombre; } set { nombre = value ?? string.Empty; } } /// <summary> /// Mtodo utilizado para que la mascota se presente /// </summary> public void Presentarse() { Console.Write("Me llamo {0} ", this.Nombre); Console.Write("soy un {0} ", this.GetType()); } } }

Como pueden ver, la clase cuenta con el constructor por defecto (siempre es bueno escribirlo, en especial si hay otros constructores); un constructor especializado que nos permitir crear objetos del tipo Mascota indicando el nombre de la misma. La estructura interna cuenta con una cadena para almacenar el nombre de la mascota y se implementa una propiedad que facilita el acceso a ese campo, en este caso se muestra un operador interesante que cuenta C# a partir del Framework 3.0 en adelante (vean el manual). Finalmente est un mtodo que permite a cada objeto del tipo Mascota que se presente, ste mtodo muestra el nombre de la mascota y su tipo, GetType() es un mensaje que todos los objetos entienden y devuelve una cadena con su tipo o nombre de clase.

Objetos Herencia y Polimorfismo

Ahora podemos probar esa clase en Program.cs codificando lo siguiente:


1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: using System; namespace Herencia1 { class Program { static void Main(string[] args) { Mascota miGato = new Mascota("Pulgoso"); miGato.Presentarse(); } } }

La salida es la siguiente:

Genial, ya logramos que el objeto nos diga su nombre y el tipo. Ahora necesitamos crear objetos de distintos tipos, como ser Perro, Gato o Pato; para ello implementamos las subclases (aquellas que se derivan de Mascota). Cdigo de Perro.cs
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: using System; namespace Herencia1 { /// <summary> /// Especializacin de la clase Mascota /// </summary> public class Perro : Mascota { /// <summary> /// Constructor especializado (los constructores no se heredan) /// </summary> /// <param name="nombre">Nombre del perro</param> public Perro(string nombre) : base(nombre) // invola el constructor de la clase base { } /// <summary> /// Mtodo propio para que un perro se presente /// </summary> public void Presentarse() { base.Presentarse(); Console.WriteLine("GUAU GUAU"); }

Objetos Herencia y Polimorfismo


25: 26: } }

Observen que al lado del nombre de la clase "Perro" se pone ": Mascota", con eso estamos indicando que la clase Perro se deriva de la clase Mascota. Una cuestin importante es que los constructores no se heredan todo lo dems si se hereda; por esa razn hace falta codificar un constructor para esta clase y por supuesto vamos a invocar al constructor de la clase base (ver lnea 15). Del mismo modo podemos invocar el mtodo Presentarse() de la clase base (lnea 22) y luego mostrar el "ruido" que los objetos de esta clase pueden hacer. El cdigo de Gato.cs es el siguiente:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: using System; namespace Herencia1 { /// <summary> /// Especializacin de la clase Mascota /// </summary> public class Gato : Mascota { /// <summary> /// Constructor especializado (los constructores no se heredan) /// </summary> /// <param name="nombre">Nombre del gato</param> public Gato(string nombre) : base(nombre) { } /// <summary> /// Mtodo propio para que un gato se presente /// </summary> public void Presentarse() { base.Presentarse(); Console.WriteLine("MIAU MIAU"); } } }

Y el cdigo de Pato.cs es casi lo mismo:


1: 2: 3: 4: 5: 6: 7: 8: 9: using System; namespace Herencia1 { /// <summary> /// Especializacin de la clase Mascota /// </summary> public class Pato : Mascota {

Objetos Herencia y Polimorfismo


10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: /// <summary> /// Constructor especializado (los constructores no se heredan) /// </summary> /// <param name="nombre">Nombre del pato</param> public Pato(string nombre) : base(nombre) { } /// <summary> /// Mtodo propio para que un pato se presente /// </summary> public void Presentarse() { base.Presentarse(); Console.WriteLine("CUAC CUAC"); } } }

Ahora podemos probar la creacin de distintos objetos para cada subclase, en Program.cs escribimos:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: using System; namespace Herencia1 { class Program { static void Main(string[] args) { Perro perro = new Perro("Sultan"); Gato gato = new Gato("Garfield"); Pato pato = new Pato("Lucas"); Console.WriteLine("\nDesde cada uno de los objetos directamente"); perro.Presentarse(); gato.Presentarse(); pato.Presentarse(); } } }

La salida es la siguiente:

Logramos lo que queramos, podemos crear objetos de distintos tipos de mascotas y cuando les pedimos que se presenten reutilizan el cdigo que se encuentra en la clase base.

Objetos Herencia y Polimorfismo

Bien como los perros, gatos y patos son todos mascotas podramos necesitar un arreglo de mascotas y pedirle a cada una de las mascotas que estn en el arreglo que se presente. Bueno eso no parece tan difcil el cdigo en Program.cs puede ser el siguiente:
1: using System; 2: 3: namespace Herencia1 4: { 5: class Program 6: { 7: static void Main(string[] args) 8: { 9: Perro perro = new Perro("Sultan"); 10: Gato gato = new Gato("Garfield"); 11: Pato pato = new Pato("Lucas"); 12: 13: Console.WriteLine("\nDesde cada uno de los objetos directamente"); 14: perro.Presentarse(); 15: gato.Presentarse(); 16: pato.Presentarse(); 17: 18: Mascota[] bichos = new Mascota[8]; 19: bichos[0] = new Perro("Sultan 2") as Mascota; 20: bichos[1] = new Perro("Diablo") as Mascota; 21: bichos[2] = new Pato("Lucas 2") as Mascota; 22: bichos[3] = new Gato("Silvestre") as Mascota; 23: bichos[4] = new Gato("Midnight") as Mascota; 24: bichos[5] = (Mascota)perro; 25: bichos[6] = (Mascota)gato; 26: bichos[7] = (Mascota)pato; 27: 28: Console.WriteLine("\nDesde un arreglo de objetos sin saber que subtipo es cada uno de ellos"); 29: foreach (Mascota bicho in bichos) 30: { 31: bicho.Presentarse(); 32: } 33: } 34: } 35: }

En la lnea 18 se declara un "arreglo" de objetos del tipo Mascota, luego en cada posicin del arreglo se "pone" un objeto realizando la conversin de tipo (casting) desde el tipo especfico a Mascota. Finalmente mediante un ciclo iterativo se le pide a cada elemento del arreglo que se presente (todos son del tipo Mascota en consecuencia entienden el mensaje Presentarse()). La salida es la siguiente:

Objetos Herencia y Polimorfismo

UN DESASTRE TOTAL !!! Resulta que cuando le pedimos a un objeto del tipo Perro que se presente lo hace correctamente y cuando lo hacemos al mismo objeto que est en una de las posiciones del arreglo no lo hace... Estamos en presencia de un problema ocasionado por lo que se conoce como Enlace (binding) esttico y dinmico. Ocurre que en la lnea 14 de Program.cs se le pide a un objeto del tipo Perro que se presente, y lo hace correctamente (esto es as porque el enlace es esttico y ejecuta el mtodo que est en la clase Perro). En cambio en la lnea 31, cuando le pedimos al objeto que est en el arreglo que se presente, tambin lo hace correctamente (indudablemente utilizando el enlace esttico) pero ahora el objeto es del tipo Mascota (as es como se lo ve). Para implementar enlace dinmico (esto significa que en tiempo de ejecucin el objeto debe determinar de que tipo es y ejecutar el mtodo correspondiente) necesitamos hacer unos cambios.

Primero debemos calificar como "virtual" el mtodo de la clase base que queremos que tenga enlace dinmico, de manera que en la clase Mascota ponemos lo siguiente:
1: 2: 3: 4: 5: 6: 7: 8: /// <summary> /// Mtodo utilizado para que la mascota se presente /// </summary> public virtual void Presentarse() { Console.Write("Me llamo {0} ", this.Nombre); Console.Write("soy un {0} ", this.GetType()); }

Esto nos permite sobre escribir el mtodo (es ms esto resulta obligatorio, porque sino sigue igual). De manera que en cada clase derivada se debe poner el calificador "override" al mtodo Presentarse()
1: 2: 3: /// <summary> /// Mtodo propio para que un perro se presente /// </summary>

Objetos Herencia y Polimorfismo


4: 5: 6: 7: 8: public override void Presentarse() { base.Presentarse(); Console.WriteLine("GUAU GUAU"); }

Pueden probar cambiando solamente en una de las clases derivadas, la salida cuando se cambia en todas es la siguiente:

Ahora si, an cuando en el arreglo los objetos se manipulan como del tipo Mascota cada uno de ellos reconoce su tipo especializado y ejecuta el mtodo correcto de acuerdo a ello. Esto es lo que se conoce como POLIMORFISMO. Bsicamente se trata de tener una coleccin de objetos, donde cada uno de ellos entiende un mensaje (en este caso Presentarse()) y de acuerdo a su tipo ejecuta el mtodo correcto.

Nota1: No hace falta invocar el mtodo de la clase base, en este ejemplo lo hice porque esa porcin de cdigo es comn para todas las subclases. Nota2: En Java la cosa es de otra manera, se puede sobre escribir los mtodos sin ninguna calificacin especial pero existe un calificador "final" que indica que ese mtodo es el ltimo y no se puede sobre escribir; esto resulta interesante cuando se desea que una mtodo o clase (tambin se puede aplicar a la clase completa) no pueda ser derivada y consecuentemente alterado su comportamiento. En C# esto se puede lograr con el calificador "sealed". Nota3: En C# se puede indicar "new" en lugar de "override" con lo cual se est indicando que el mtodo (el de la clase derivada) mantiene el nombre pero es nuevo; esto tiene otros beneficios que exceden el ejemplo.

Espero que les sirva.

Potrebbero piacerti anche