Vous êtes sur la page 1sur 17

Mi Primer Objeto - parte 2

Vamos a continuar con la realizacin del objeto Bolsa que planteamos en la primer parte de esta publicacin. En este caso vamos a trabajar sobre la comparacin de objetos, el concepto de igual y el concepto de idntico. Tambin veremos algo sobre constructores y finalmente implementaremos la clase Bolsa para objetos.

En la teora de programacin orientada a objetos aprendemos que los objetos tienen "identidad", lo que significa que cada objeto (como las personas) son nicos, pueden contener los mismos datos lo que significa que son "iguales" pero nunca sern "idnticos". La mejor forma de visualizar esta situacin es con el siguiente cdigo:
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: 27: 28: static void Main(string[] args) { int[] v1 = new int[] { 1, 2, 3 }; int[] v2 = new int[] { 1, 2, 3 }; Console.Write("\nv1 : "); for (int i = 0; i < v1.Length; ++i) { Console.Write("{0} ", v1[i]); } Console.Write("\nv2 : "); for (int i = 0; i < v2.Length; ++i) { Console.Write("{0} ", v2[i]); } Console.Write("\nEl mtodo Equals devuelve "); if (v1.Equals(v2)) { Console.WriteLine("IGUALES"); } else { Console.WriteLine("DISTINTOS"); } }

Como pueden ver se declara dos "arreglos" de enteros y se inicializan con los mismos valores; a continuacin se muestra el contenido de cada arreglo y luego se invoca el mtodo "Equals" que tienen estos objetos. El mtodo "Equals" est implementado en la primer clase de la jerarqua de clases del lenguaje, es un mtodo de la clase "objetc", absolutamente todas las implementaciones que ya vienen con el Framework o que nosotros hagamos heredan ese mtodo. A continuacin se muestra la salida de este programa:

Mi Primer Objeto - parte 2

Dice que los vectores son DISTINTOS !!! Lo cual es correcto, porque cada uno de esos vectores hace referencia a dos zonas diferentes en el Heap, recordemos que cada objeto tiene un rea de memoria en el Stack donde se guarda la referencia y otra rea de memoria en el Heap donde se guarda el objeto mismo, esto se explica en Estructura de Datos y Programacin Orientada a Objetos. Consecuentemente cuando se invoca el mtodo Equals de un objeto lo que se compara es la direccin del rea de memoria del Heap a la cual est haciendo referencia. Esto se puede ver mejor en el siguiente esquema:

Lo importante es que a todos los objetos se les puede invocar el mensaje Equals para averiguar si ul objeto en cuestin es o no igual a otro objeto, el problema es que si nosotros no escribimos el cdigo entonces el resultado siempre ser DISTINTO (falso). Lo que debemos hacer es sobre escribir el mtodo que se hereda de la clase "object" y implementar nuestra propia versin de la comparacin, aquel cdigo que compare lo que nosotros necesitamos que se compare para determinar la igualdad. Es importante tomarse un momento para pensar esta situacin porque las especificaciones que nosotros escribamos seguramente se utilizarn en otras implementaciones que pueden necesitar de este comportamiento. El siguiente cdigo implemente nuestro mtodo Equals
1: 2: 3: 4: 5: /// /// /// /// /// <summary> Determina si el objeto del tipo Bolsa es igual a la bolsa que se pasa como argumento. Todos los elementos de una bolsa deben existir en la otra bolsa, el control debe realizarse en ambas para superar el siguiente caso

Mi Primer Objeto - parte 2


6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: emisor 17: 18: 19: 20: 21: 22: 23: parmetro 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: /// bolsa1 = ['A', 'B', 'B'] /// bolsa2 = ['A', 'B', 'C'] /// /// </summary> /// <param name="otra">Objeto del tipo /// <returns>Verdadero si ambas bolsas public bool Equals(Bolsa otra) { if ((otra != null) && (this.cantidad { for (int i = 0; i < this.cantidad; { if (!otra.Existe(this.datos[i])) { return false; } } for (int i = 0; i < otra.cantidad; ++i) // este ciclo controla el objeto { if (!this.Existe(otra.datos[i])) { return false; } } return true; } return false; }

bolsa con el que se compara</param> son iguales</returns> == otra.cantidad)) ++i) // este ciclo controla el objeto

Este mtodo lo que hace es recibir como parmetro un objeto del tipo Bolsa, y si la cantidad de elementos de ambas el objeto emisor (el que ejecuta el mtodo) y el objeto parmetro son iguales procede a controlar que cada elemento de una bolsa exista en la otra. El punto es que todava no es modificado el mtodo que se hereda de la clase "object", eso es porque ese mensaje/mtodo tiene la siguiente firma "bool Equals(object obj)", recibe como parmetro un "object" no recibe una "Bolsa". Para evitar que futuros usos de nuestro objeto fracasen debemos sobre escribir el mtodo heredado.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: /// <summary> /// Determina si el objeto (Bolsa) es igual al objeto que se pasa /// como argumento. La nica posibilidad es que el argumento tambin /// sea del tipo Bolsa. /// </summary> /// <param name="obj">Objeto con el que se compara</param> /// <returns>verdadero si ambos objetos son iguales</returns> public override bool Equals(object obj) { if ((obj != null) && (obj is Bolsa)) { return Equals((Bolsa)obj); } return false; }

Mi Primer Objeto - parte 2

Con ste cdigo podemos estar seguros que se realizar la comparacin que queremos. Se debe destacar que hace falta la palabra reservada "override" para indicar que sobre escribimos el mtodo heredado; se controla que el parmetro no sea nulo y en caso de ser vlido que sea del tipo Bolsa para invocar nuestro mtodo Equals. Nota: Cuando escriban este cdigo o algo parecido el entorno de desarrollo del Visual Studio va a mostrar un mensaje de advertencia o warning que dice "Se est sobre escribiendo Equals pero no se sobre escribe GetHashCode". Esto es as porque en general para determinar si un objeto es igual a otro se suele utilizar tcnicas de hash para generar un nmero que surge de los valores internos del objeto. La advertencia o warning no es un error, de manera que la aplicacin puede funcionar. Pero es mejor evitar todas las advertencias entonces se puede agregar el siguiente mtodo que sobre escribe el que se hereda.
1: 2: 3: 4: 5: 6: 7: 8: 9: /// <summary> /// Gener un nmero, mediante tcnicas hash que se corresponde con el /// contenido interno del objeto. /// </summary> /// <returns>Valor del cdigo hash</returns> public override int GetHashCode() { return base.GetHashCode(); }

Este cdigo lo nico que hace es invocar el mismo mtodo pero de la clase base, por eso utiliza otra pseudovariable "base". Cuando realicemos ejercicios de jerarqua de clases veremos con ms detalle esta pseudovariable. Esto es solo para no tener la advertencia molestando a cada rato.

Algo sobre constructores: En la teora nos ensean que los objetos se crean gracias a un mtodo conocido como "constructor" que es el encargado de inicializar los elementos de la estructura interna de un objeto. En nuestro ejemplo de Bolsa nos hemos encargado de fijar los valores iniciales de cada elemento (el arreglo y el entero) de manera que no hace falta un constructor, sin embargo sabemos que aunque no lo implementemos este mtodo est disponible. Veamos cmo quedara nuestro ejemplo si codificamos el constructor por defecto (aquel que no tiene parmetros).
1: 2: 3: 4: 5: 6: 7: 8: 9: /// <summary> /// Constructor por defecto, incializa los elementos de la estructura /// interna del objeto. /// </summary> public Bolsa() { datos = new char[100]; cantidad = 0; }

Mi Primer Objeto - parte 2

Simplemente se inicializa el arreglo (lista en secuencia) y tambin el entero que mantiene la cantidad de elementos tiles dentro de la bolsa. Recordemos que los constructores no devuelven tipo, es ms ni siquiera se pone "void". Es importante corregir la declaracin del elemento "datos" en la estructura interna porque si la dejamos como est (private char[] datos = new char[100];) se inicializa dos veces lo que no es necesario, dado que estaramos reservando memoria en el heap que inmediatamente despus cuando se ejecuta el constructor se deja sin referenciar.
1: 2: 3: 4: 5: /// <summary> /// sirve para almacenar o guardar los elementos dentro del objeto /// inicialmente tiene una capacidad para 100 caracteres. /// </summary> private char[] datos;

Parece que codificar este constructor no agrega nada interesante porque su trabajo ya se haca en la declaracin de la estructura interna, lo que ocurre es que la intencin es implementar otros constructores (especializados) y por esa razn es que hace falta implementar el constructor por defecto. Por ejemplo, puede ocurrir que sea necesario contar con algn objeto del tipo Bolsa que siempre va a contener entre 5 a 10 elementos, de manera que asignar un "arreglo" de 100 elementos es un desperdicio. Esto se puede solucionar con un constructor especializado en el cual sea posible indicar el tamao inicial del arreglo.
1: /// <summary> 2: /// Constructor especializado, permite indicar el tamao o dimensin 3: /// del contenedor (arreglo) para los elementos de la Bolsa. 4: /// </summary> 5: /// <exception cref="ArgumentException"> 6: /// Dispara la excepcin de argumento invlido cuando el parametro es cero o menor 7: /// </exception> 8: /// <param name="dimension">Tamao incial del contenedor (debe ser mayor que cero)</param> 9: public Bolsa(int dimension) 10: { 11: if (dimension > 0) 12: { 13: datos = new char[dimension]; 14: cantidad = 0; 15: } 16: else 17: { 18: throw new ArgumentException("Argumento incorrecto, dimension = " + dimension.ToString()); 19: } 20: }

Ahora es posible "crear" un objeto del tipo Bolsa que incialmente tenga espacio para 10 elementos.
1: 2: Bolsa unabolsacomun = new Bolsa(); Bolsa unabolsachica = new Bolsa(10);

Mi Primer Objeto - parte 2

Otra posibilidad es que sea necesario "crear" un objeto del tipo Bolsa que sea una copia de otra bolsa. Esto es lo que se conoce como el Constructor Copia.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: /// <summary> /// Constructor especializado, permite crear un objeto como copia de otra /// </summary> /// <exception cref="ArgumentException"> /// Dispara la excepcin de argumento invlido cuando el parametro es nulo o /// no es del tipo Bolsa /// </exception> /// <param name="origen">objeto del tipo Bolsa que se copia</param> public Bolsa(Bolsa origen) { if ((origen != null) && (origen is Bolsa)) { datos = new char[origen.cantidad]; cantidad = origen.cantidad; for (int i = 0; i < cantidad; ++i) { datos[i] = origen.datos[i]; } } else { throw new ArgumentException("Argumento incorrecto, origen = null"); } }

Observen que las ltimas porciones de cdigo cuentan con instrucciones para controlar posibles errores que un programador puede cometer, como ser enviar un tamao (dimensin) igual o menor que cero, esto provocara un error en tiempo de ejecucin o en el otro caso tratar de crear un objeto del tipo Bolsa a partir de un objeto null (no inicializado) o un objeto que no es Bolsa.

Bien, podemos decir que se ha cumplido la segunda iteracin dado que tenemos un producto (en este caso un prototipo) que implementa todo el comportamiento que observamos cuando comenzamos el ejercicio. Es posible agregar elementos, sacarlos, averiguar si un elemento est en el objeto, contar cuantos elementos tiene el objeto, contar cuantos elementos de un valor en particular hay en el objeto, obtener una cadena con la representacin de los elementos que el objeto tiene, y otros mensajes que hicieron falta para completar y mejorar ese comportamiento. Obviamente el cdigo debe revisarse, seguramente hay quienes (saben algo ms de programacin) y piensan que puede implementarse de otra manera, con lo que estoy de acuerdo. Pero recordemos que esta publicacin trata de introducir a los "novatos" en la programacin orientada a objetos, dejemos la mejora del cdigo para otro momento. El siguiente paso o iteracin es convertir el prototipo en un producto que permita realizar todo ese comportamiento con elementos que vimos en el enunciado o dominio del ejercicio, por ejemplo artculos del supermercado.

Mi Primer Objeto - parte 2

Indudablemente, si estamos en programacin orientada a objetos un artculo es un objeto que tiene un comportamiento en particular, para comenzar podemos decir que hace falta que este objeto (artculo) pueda entregar una cadena con informacin sobre el artculo mismo y tambin que se pueda comparar un objeto del tipo artculo con otro (obviamente del mismo tipo) para ver si son iguales o no. En otras palabras necesitamos implementar los mensajes ToString y Equals. Como estructura interna de los objetos del tipo artculo vamos a considerar un entero que ser el cdigo del artculo, una cadena para la descripcin y un precio. Una forma de indicar toda esa especificacin es el siguiente artefacto (esto viene de UML)

Se est indicando los elementos de la estructura interna (privados) de cada objeto (por eso el signo "-" delante de cada elemento) tambin se indica los mensajes que cada objeto entiende, que de hecho son pblicos (por eso el signo "+" delante de cada mensaje). Para ser prolijos debemos agregar un elemento al proyecto, obviamente es una clase y el nombre apropiado es "Articulo", recuerden que las buenas prcticas de programacin dicen que los nombres de clases deben ser sustantivos y comienzan con la primer letra en maysculas. A continuacin tenemos el cdigo para esta clase.
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: using using using using System; System.Collections.Generic; System.Linq; System.Text;

namespace DemoObjeto2 { public class Articulo { #region Campos de la Estructura Interna de cada objeto /// <summary> /// sirve para almacenar el cdigo de un objeto del tipo Articulo /// </summary> private int codigo; /// <summary> /// sirve para almacenar la descripcin del objeto del tipo Articulo /// </summary> private string descripcion; /// <summary> /// Sirve para almacenar el precio del objeto del tipo Articulo /// </summary> private decimal precio; #endregion

Mi Primer Objeto - parte 2


26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82:

#region Constructores /// <summary> /// Constructor por defecto, inicializa la estructura interna del objeto /// </summary> public Articulo() { codigo = 0; descripcion = ""; precio = 0M; // El sufijo "M" indica que se trata de un decimal } /// <summary> /// Constructor especializado en el que se facilitan todos los valores /// mediante los parmetros /// </summary> /// <param name="codigo">cdigo del articulo</param> /// <param name="descripcion">descripcin del articulo</param> /// <param name="precio">precio del artculo</param> public Articulo(int codigo, string descripcion, decimal precio) { this.codigo = codigo; this.descripcion = String.Copy(descripcion); this.precio = precio; } /// <summary> /// Constructor especializado en el que se facilitan todos los valores /// mediante los parmetros /// Este constructor es para poder pasar parmetros del tipo double /// </summary> /// <param name="codigo">cdigo del articulo</param> /// <param name="descripcion">descripcin del articulo</param> /// <param name="precio">precio del artculo</param> public Articulo(int codigo, string descripcion, double precio) : this(codigo, descripcion, (decimal)precio) { } /// <summary> /// Constructor copia, inicializa un nuevo objeto igual al parmetro /// </summary> /// <param name="origen">Articulo que se copia</param> public Articulo(Articulo origen) : this(origen.codigo, origen.descripcion, origen.precio) { } #endregion #region Mtodos pblicos, implementan los mensajes /// /// /// /// /// <summary> Determina si el objeto de tipo Articulo es igual a otro Articulo </summary> <param name="obj">Objeto con el que se compara</param> <returns>Verdadero si los cdigos de ambos son iguales</returns>

Mi Primer Objeto - parte 2


83: public bool Equals(Articulo obj) 84: { 85: if (obj != null) 86: { 87: return this.codigo == obj.codigo; 88: } 89: return false; 90: } 91: 92: /// <summary> 93: /// Determina si el objeto (Articulo) es igual al objeto que se pasa 94: /// como argumento. La nica posibilidad es que sean del mismo tipo 95: /// </summary> 96: /// <param name="obj">Objeto con el que se compara</param> 97: /// <returns>verdadero si ambos objetos son iguales</returns> 98: public override bool Equals(object obj) 99: { 100: if ((obj != null) && (obj is Articulo)) 101: { 102: return Equals((Articulo)obj); 103: } 104: return false; 105: } 106: /// <summary> 107: /// Gener un nmero, mediante tcnicas hash que se corresponde con el 108: /// contenido interno del objeto. 109: /// </summary> 110: /// <returns>Valor del cdigo hash</returns> 111: public override int GetHashCode() 112: { 113: return base.GetHashCode(); 114: } 115: 116: /// <summary> 117: /// Genera una cadena con la representacin de los elementos de la 118: /// estructura interna del objeto 119: /// </summary> 120: /// <returns>cadena con informacin del objeto</returns> 121: public override string ToString() 122: { 123: return codigo.ToString() + " - " + descripcion + " : " + precio.ToString(); 124: } 125: 126: #endregion 127: 128: 129: } 130: }

El ejemplo de la clase Articulo es interesante para analizar y aprender. Utiliza String.Copy(...) porque de esa manera logramos que el elemento de la estructura interna de un objeto del tipo Articulo tenga su propia rea de memoria para la descripcin, si utilizramos el operador de asignacin "=" estaramos tomando solo la referencia. El otro punto interesante es como desde un constructor se invocan otro (lneas 62 y 71). El resto ya se comento en esta publicacin o en la anterior de la serie.

Mi Primer Objeto - parte 2

El cdigo para probar esto puede ser el siguiente (siempre es recomendable probar lo que estamos haciendo)
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: using using using using System; System.Collections.Generic; System.Linq; System.Text;

namespace DemoObjeto2 { class Program { static void Main(string[] args) { Articulo a = new Articulo(1, "uno", 15.0); Console.WriteLine("a : {0}", a.ToString()); Articulo b = new Articulo(2, "dos", 55.5); Console.WriteLine("b : {0}", b.ToString()); Articulo c = new Articulo(a); Console.WriteLine("c : {0}", c.ToString()); } } }

Ahora hay que modificar la implementacin de la clase Bolsa para que opere con objetos del tipo Articulo. Esto se puede hacer por partes, como se fue desarrollando el prototipo o (con un poco de coraje) cambiarlo todo de una sola vez. A continuacin esta el cdigo completo y luego las explicaciones que correspondan
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: 27: 28: using using using using System; System.Collections.Generic; System.Linq; System.Text;

namespace DemoObjeto2 { /// <summary> /// Definicin para aquellos objetos que presentan el comportamiento /// asociado con una "bolsa" que contine "elementos", en la bolsa se /// puede agregar o sacar elementos, tambine es posible averiguar si /// est vaca, o cuantos elementos tiene en total as como cuantos /// elementos de algun valor hay. /// /// Implementa la bolsa para objetos del tipo Articulo /// /// </summary> public class Bolsa { #region Campos de la Estructura Interna de cada objeto /// <summary> /// sirve para almacenar o guardar los elementos dentro del objeto /// inicialmente tiene una capacidad para 100 caracteres. /// </summary> private Articulo[] datos; /// <summary>

10

Mi Primer Objeto - parte 2


29: /// Sirve para mantener la cantidad de elementos tiles dentro del 30: /// objeto, inicialmente su valor es cero. 31: /// </summary> 32: private int cantidad = 0; 33: 34: #endregion 35: 36: #region Constructores 37: 38: /// <summary> 39: /// Constructor por defecto, incializa los elementos de la estructura 40: /// interna del objeto. 41: /// </summary> 42: public Bolsa() 43: { 44: datos = new Articulo[100]; 45: cantidad = 0; 46: } 47: 48: /// <summary> 49: /// Constructor especializado, permite indicar el tamao o dimensin 50: /// del contenedor (arreglo) para los elementos de la Bolsa. 51: /// </summary> 52: /// <exception cref="ArgumentException"> 53: /// Dispara la excepcin de argumento invlido cuando el parametro es cero o menor 54: /// </exception> 55: /// <param name="dimension">Tamao incial del contenedor (debe ser mayor que cero)</param> 56: public Bolsa(int dimension) 57: { 58: if (dimension > 0) 59: { 60: datos = new Articulo[dimension]; 61: cantidad = 0; 62: } 63: else 64: { 65: throw new ArgumentException("Argumento incorrecto, dimension = " + dimension.ToString()); 66: } 67: } 68: 69: /// <summary> 70: /// Constructor especializado, permite crear un objeto como copia de otra 71: /// </summary> 72: /// <exception cref="ArgumentException"> 73: /// Dispara la excepcin de argumento invlido cuando el parametro es nulo o 74: /// no es del tipo Bolsa 75: /// </exception> 76: /// <param name="origen">objeto del tipo Bolsa que se copia</param> 77: public Bolsa(Bolsa origen) 78: { 79: if ((origen != null) && (origen is Bolsa)) 80: { 81: datos = new Articulo[origen.cantidad]; 82: cantidad = origen.cantidad;

11

Mi Primer Objeto - parte 2


83: for (int i = 0; i < cantidad; ++i) 84: { 85: // hay que copiar el articulo 86: datos[i] = new Articulo(origen.datos[i]); 87: } 88: } 89: else 90: { 91: throw new ArgumentException("Argumento incorrecto, origen = null"); 92: } 93: } 94: 95: #endregion 96: 97: 98: #region Mtodos pblicos, implementan los mensajes 99: 100: /// <summary> 101: /// Agrega un elemento al objeto del tipo bolsa 102: /// </summary> 103: /// <param name="x">Elemento que se desea agregar</param> 104: /// <returns>Referencia al mismo objeto bolsa que ahora continene el nuevo elemento</returns> 105: public Bolsa Agregar(Articulo x) 106: { 107: if (cantidad == datos.Length) 108: { 109: Articulo[] nuevo = new Articulo[datos.Length + 50]; 110: for (int i = 0; i < datos.Length; ++i) 111: { 112: // Aqu no hace falta copiar el articulo, basta con pasar la referencia 113: nuevo[i] = datos[i]; 114: } 115: datos = nuevo; 116: } 117: datos[cantidad] = x; 118: ++cantidad; 119: return this; 120: } 121: 122: /// <summary> 123: /// Cuenta cuntos elementos hay en un objeto del tipo bolsa 124: /// </summary> 125: /// <returns>Cantidad de elementos que hay en el objeto bolsa</returns> 126: public int Contar() 127: { 128: return cantidad; 129: } 130: 131: /// <summary> 132: /// Cuenta cuntos elemetnos de un determinado valor se encuentran dentro 133: /// de un objeto del tipo bolsa 134: /// </summary> 135: /// <param name="x">Valor que se desea averiguar</param> 136: /// <returns>Cantidad de elementos del valor dado que hay en el objeto bolsa</returns>

12

Mi Primer Objeto - parte 2


137: public int Contar(Articulo x) 138: { 139: int cuenta = 0; 140: for (int i = 0; i < cantidad; ++i) 141: { 142: // Es necesario utilizar el mensaje Equals 143: if (datos[i].Equals(x)) 144: { 145: ++cuenta; 146: } 147: } 148: return cuenta; 149: } 150: 151: /// <summary> 152: /// Averigua si un elemento est o no dentro de un objeto del tipo bolsa 153: /// </summary> 154: /// <param name="x">Elemento que se desea controlar</param> 155: /// <returns>Verdadero si el elemento est en la bolsa, caso contrario falso</returns> 156: public bool Existe(Articulo x) 157: { 158: for (int i = 0; i < cantidad; ++i) 159: { 160: if (datos[i].Equals(x)) 161: { 162: return true; 163: } 164: } 165: return false; 166: } 167: 168: /// <summary> 169: /// Saca o retira el elemento indicado del objeto del tipo bolsa, 170: /// </summary> 171: /// <param name="x">Elemento a retirar o sacar</param> 172: /// <returns>Referencia al miso objeto bolsa sin el elemento indicado</returns> 173: public Bolsa Sacar(Articulo x) 174: { 175: if (Existe(x)) 176: { 177: int i = 0; 178: while (!datos[i].Equals(x)) 179: { 180: ++i; 181: } 182: for (; i < cantidad - 1; ++i) 183: { 184: datos[i] = datos[i + 1]; 185: } 186: // Es necesario desreferenciar el ltimo elemento 187: datos[cantidad] = null; 188: --cantidad; 189: } 190: return this; 191: }

13

Mi Primer Objeto - parte 2


192: 193: /// <summary> 194: /// Genera una cadena con todos los elementos que hay en el objeto 195: /// del tipo bolsa. 196: /// </summary> 197: /// <remarks> 198: /// ESTA NO ES LA MEJOR IMPLEMENTACIN, PERO SIRVE PARA EL EJEMPLO 199: /// DEBERA UTILIZARSE UN OBJETO StringBuilder (luego lo veremos) 200: /// </remarks> 201: /// <returns>Cadena con la representacin de cada elemento que hay en el objeto bolsa</returns> 202: public override string ToString() 203: { 204: string s = ""; 205: for (int i = 0; i < cantidad; ++i) 206: { 207: s = s + datos[i].ToString() + " "; 208: } 209: return s; 210: } 211: 212: 213: /// <summary> 214: /// Determina si el objeto (Bolsa) es igual al objeto que se pasa 215: /// como argumento. La nica posibilidad es que el argumento tambin 216: /// sea del tipo Bolsa. 217: /// </summary> 218: /// <param name="obj">Objeto con el que se compara</param> 219: /// <returns>verdadero si ambos objetos son iguales</returns> 220: public override bool Equals(object obj) 221: { 222: if ((obj != null) && (obj is Bolsa)) 223: { 224: return Equals((Bolsa)obj); 225: } 226: return false; 227: } 228: 229: /// <summary> 230: /// Gener un nmero, mediante tcnicas hash que se corresponde con el 231: /// contenido interno del objeto. 232: /// </summary> 233: /// <returns>Valor del cdigo hash</returns> 234: public override int GetHashCode() 235: { 236: return base.GetHashCode(); 237: } 238: 239: /// <summary> 240: /// Determina si el objeto del tipo Bolsa es igual a la bolsa que se 241: /// pasa como argumento. 242: /// Todos los elementos de una bolsa deben existir en la otra bolsa, 243: /// el control debe realizarse en ambas para superar el siguiente caso 244: /// bolsa1 = ['A', 'B', 'B'] 245: /// bolsa2 = ['A', 'B', 'C'] 246: /// 247: /// </summary>

14

Mi Primer Objeto - parte 2


248: 249: 250: 251: 252: 253: 254: emisor 255: 256: 257: 258: 259: 260: 261: parmetro 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: } 276: } /// <param name="otra">Objeto del tipo /// <returns>Verdadero si ambas bolsas public bool Equals(Bolsa otra) { if ((otra != null) && (this.cantidad { for (int i = 0; i < this.cantidad; { if (!otra.Existe(this.datos[i])) { return false; } } for (int i = 0; i < otra.cantidad; ++i) // este ciclo controla el objeto { if (!this.Existe(otra.datos[i])) { return false; } } return true; } return false; } #endregion bolsa con el que se compara</param> son iguales</returns> == otra.cantidad)) ++i) // este ciclo controla el objeto

En primer lugar, el arreglo de la estructura interna ya no puede ser de "char" ahora debe ser de "Articulo"; esto se debe corregir en todos los lugares donde se declaran los arreglos (lneas 27, 44, 60, 81 y 109). Tambin se debe cambiar el tipo de los parmetros en Agregar, Contar, Existe y Sacar (lneas 105, 137, 156 y 173). Otras cuestiones son: En la lnea 86 (constructor copia) se debe crear un nuevo objeto a partir de otro, caso contrario ambas referencias apuntaran a la misma zona del heap; en cambio en la lnea 113 no hace falta porque se est redimensionando el arreglo de manera los objetos del viejo se pasan al nuevo y el Garbage Collector liberar solamente el espacio de la bolsa y no los de cada elemento (estos mantienen sus referencias en el nuevo arreglo). En las lneas 143, 160 y 178 se debe utilizar el mensaje Equals de los objetos del tipo Articulo para comparar con el parmetro (no es directo como con los caracteres). Finalmente en la lnea 187 (mtodo Sacar) hay que desreferenciar el ltimo elemento del arreglo para que el Garbage Collector pueda devolver esa memoria del Heap, caso contrario no tenemos acceso al elemento pero sigue estando referenciado.

15

Mi Primer Objeto - parte 2

Para probar todo esto podemos utilizar:


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: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: using using using using System; System.Collections.Generic; System.Linq; System.Text;

namespace DemoObjeto2 { class Program { static void Main(string[] args) { Articulo a = new Articulo(1, "uno", 15.0); Console.WriteLine("a : {0}", a.ToString()); Articulo b = new Articulo(2, "dos", 55.5); Console.WriteLine("b : {0}", b.ToString()); Articulo c = new Articulo(a); Console.WriteLine("c : {0}", c.ToString()); Bolsa mibolsa = new Bolsa(); mibolsa.Agregar(a); Console.WriteLine("mibolsa tiene: {0}", mibolsa.ToString()); mibolsa.Agregar(b); Console.WriteLine("mibolsa tiene: {0}", mibolsa.ToString()); mibolsa.Agregar(new Articulo(45, "otro articulo", 345.6)); Console.WriteLine("mibolsa tiene: {0}", mibolsa.ToString()); Bolsa otrabolsa = new Bolsa(mibolsa); Console.WriteLine("otrabolsa tiene: {0}", mibolsa.ToString()); mibolsa.Sacar(b); Console.WriteLine("mibolsa tiene: {0}", mibolsa.ToString()); } } }

La salida de este programa es:

Con lo cual hemos cumplido con la tercera iteracin, tenemos un producto que implementa el comportamiento observado para artculos de un supermercado.
16

Mi Primer Objeto - parte 2

Ahora tenemos que hacer lo mismo para otros objetos: armas, personas, etc. Vaya a saber uno que ser lo que tengamos que meter dentro de la bolsa, lo que es seguro es que no es posible estar codificando a cada rato la implementacin de la Bolsa cada vez que nos cambian el tipo de elementos que hay que meter adentro. Eso queda para la siguiente parte del ejemplo. Espero que les sirva.

17

Vous aimerez peut-être aussi