Programaci´n o Orientada a Objetos C#

F´lix G´mez M´rmol e o a
3o Ingenier´ Inform´tica ıa a Julio de 2004

2

´ Indice general
´ Indice General 2. Clases y Objetos 2.1. Clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1. Estructura . . . . . . . . . . . . . . . . . . . . . . . 2.1.2. Ocultaci´n de la informaci´n . . . . . . . . . . . . . o o 2.1.3. Relaciones entre clases: Cliente-Servidor y Herencia 2.1.4. Visibilidad . . . . . . . . . . . . . . . . . . . . . . . 2.2. Objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3. Mensajes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.1. Sintaxis. Notaci´n punto . . . . . . . . . . . . . . . . o 2.3.2. Sem´ntica . . . . . . . . . . . . . . . . . . . . . . . . a 2.4. Sem´ntica referencia versus sem´ntica almacenamiento . . . a a 2.5. Creaci´n de objetos . . . . . . . . . . . . . . . . . . . . . . o 2.5.1. Destructores . . . . . . . . . . . . . . . . . . . . . . 2.6. Sem´ntica de la asignaci´n e igualdad entre objetos . . . . . a o 2.7. Genericidad . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.8. Definici´n de una clase “Lista Doblemente Enlazada” . . . o 3. Dise˜ o por Contrato: Asertos y Excepciones n 3.1. Contrato software . . . . . . . . . . . . . . . . 3.2. Clases y Correcci´n del software: Asertos . . o 3.3. Excepciones en C# . . . . . . . . . . . . . . . 3.3.1. Lanzamiento de excepciones . . . . . . 3.3.2. Bloques try . . . . . . . . . . . . . . . 3.3.3. Manejadores . . . . . . . . . . . . . . 3.4. Conversi´n de asertos en excepciones . . . . . o 4. Herencia 4.1. Introducci´n . . . . . . . . . . . . . . . . . o 4.2. Doble aspecto de la herencia . . . . . . . . 4.3. Polimorfismo . . . . . . . . . . . . . . . . 4.3.1. Sobrecarga . . . . . . . . . . . . . 4.3.2. Regla de aplicaci´n de propiedades o 4.3.3. Estructuras de datos polim´rficas . o 4.3.4. Operadores is y as . . . . . . . . 4.4. Ligadura Din´mica . . . . . . . . . . . . . a 4.5. Clases Diferidas . . . . . . . . . . . . . . . 4.5.1. Interfaces . . . . . . . . . . . . . . 4.6. Herencia, reutilizaci´n y extensibilidad del o 4.7. Herencia m´ltiple . . . . . . . . . . . . . . u 3 4 5 5 5 7 8 9 10 10 10 10 11 11 12 12 14 14 17 17 17 18 20 21 22 22 25 25 26 26 27 29 29 29 30 31 32 34 37

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . software . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

4

´ INDICE GENERAL

4.7.1. Problemas: Colisi´n de nombres y herencia repetida . . . . . . . . . . o 4.7.2. Ejemplos de utilidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.8. C#, Java y C++: Estudio comparativo . . . . . . . . . . . . . . . . . . . . . ´ Indice de Figuras ´ Indice de Tablas ´ Indice de C´digos o Bibliograf´ ıa

37 38 39 41 43 45 47

1 Una clase es una implementaci´n total o parcial de un tipo abstracto de o o dato (TAD). 2. Sus caracter´ ısticas m´s destacables son que se trata de entidades sint´cticas y que descria a ben objetos que van a tener la misma estructura y el mismo comportamiento.Tema 2 Clases y Objetos 2. public class Luna { public static void Main () { int luna = 238857. } } C´digo 2.1: Clase Luna o 5 . y M´todos. llamada Luna.1.1. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // Distancia hasta la Luna convertida a kil´ metros o using System . WriteLine (" De la Tierra a la Luna = " + luna + " millas ") . convierte a kil´metros la o o distancia de la Tierra a la Luna en millas. que no son m´s que operaciones aplicables sobre los objetos.609) . lunaKilo = ( int ) ( luna * 1.") . Clases Definici´n 2. WriteLine (" Kil´ metros = " o + lunaKilo + " km .1.1 La clase mostrada en el c´digo 2. que determinan una estructura de almacenamiento para cada objeto de la clase. int lunaKilo . que a partir de ahora llamaremos miembros. Console . son: Atributos. Console . e a Ejemplo 2.1. Estructura Los componentes principales de una clase.

Para declarar un tipo consistente en un conjunto etiquetado de constantes enteras se emplea la palabra clave enum (por ejemplo. 9223372036854775807) (0. 2. Alberto = 15}).7 × 1038 ) de 15 a 16 d´ ıgitos significativos −28 . abstract as base bool break byte case catch char checked class const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach get goto if implicit in int interface internal is lock long namespace new null object operator out override params private protected public readonly ref return sbyte sealed set short sizeof stackalloc static string struct switch this throw true try typeof unit ulong unchecked unsafe ushort using value virtual void volatile while Tabla 2.1.4: Palabras reservadas . e Palabras reservadas La tabla 2. enum Edades {F´lix = 21.3 muestran los tipos primitivos soportados por C#.6 Tema 2.255) {true.127) (0.9 × 10+28 ) de 28 a 29 d´ (10 ıgitos significativos Tabla 2. Clases y Objetos Tipo short ushort int uint long ulong Bytes 2 2 4 4 8 8 Rango de Valores (-32768. 65535) (-2147483648.3: Otros tipos primitivos Tipos de datos primitivos Las tablas 2. 18446744073709551615) Tabla 2. Alex.2: Tipos flotantes primitivos Tipo byte ubyte bool char Bytes 1 1 1 2 Rango de Valores (-128. 32767) (0. false} Tabla ASCII Tabla 2.4 × 1038 ) 7 d´ ıgitos significativos (±1.1: Tipos enteros primitivos Tipo float double decimal Bytes 4 8 16 Rango de Valores (±3. 4294967295) (-9223372036854775808.4 muestra las palabras reservadas de C#. 7. 2147483647) (0.2 y 2.

5. el servidor deber´ o ıa ocultar los aspectos de implementaci´n al cliente. privado y protegido. . Por ejemplo. . Ejemplo 2.2. Por ultimo. // Correcto w .3 se muestra un ejemplo de ocultaci´n de informaci´n mediante o o o el uso de get y set.2: Ejemplo de Ocultaci´n de Informaci´n o o o A diferencia de C++. public static readonly m.3 . n y m podr´ o ıamos decir que son “estructuralmente equivalentes”: public const n. . Otra pr´ctica interesante consiste en declarar un atributo como privado y.4 En el c´digo 2.2. mientras que uno con acceso p´blico es accesible desde cualquier u clase. un miembro protegido s´lo es accesible por miembros de la misma clase o ´ o bien por miembros de alguna de las subclases. mientras que con la segunda opci´n la inicializaci´n se da en o o o tiempo de compilaci´n. . // Error sint´ ctico a . . w . } } C´digo 2. o Una forma de simular el efecto de const mediante readonly es usando adem´s la palabra a clave static. Para ello nos u valemos de los modificadores de acceso get y set. mediante otro a atributo p´blico tener acceso de lectura y/o escritura sobre el atributo privado.2 En el c´digo 2. o Para llevar a cabo esto. La diferencia entre readonly y const es que con la primera opci´n la inicializaci´n tiene o o lugar en tiempo de ejecuci´n.2 se muestra un ejemplo de ocultaci´n de informaci´n. SetPunto (4. Ejemplo 2. y . Ocultaci´n de la informaci´n o o En ocasiones conviene ocultar ciertas caracter´ ısticas (atributos y/o m´todos) de una clase e al exterior. C# proporciona tres tipos de acceso: p´blico. Ejemplo 2. y = v. en C# es posible declarar un miembro como de s´lo lectura mediante o la palabra clave readonly. y . en una relaci´n entre clases de Cliente-Servidor.9) .3 En el siguiente c´digo. Obs´rvese que el identificador value es siempre un objeto del mismo tipo que el atributo e que lo contiene. .6.1 Clases 7 2. x = 5. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Punto { private double x . // O simplemente double x .1. class Test { public void Prueba ( Punto w ) { . public void SetPunto ( double u . double v ) { x = u. u Un miembro con acceso privado (opci´n por defecto) s´lo es accesible desde otros miemo o bros de esa misma clase. mediante o o o la clase Punto. . } } .

Clases y Objetos 1 2 3 4 5 6 7 8 9 10 11 12 13 public class CuentaPalabras { private string m_file_output . mientras que en la 2.a muestra la relaci´n de clientela entre A y B.b: class A: B { . si A es una versi´n especiao o lizada de B (herencia de especializaci´n).a: o o class A { . adaptable. } } } C´digo 2. y eficiente.1. } Por su parte. variable local) e es de o a tipo B. es decir.1. par´metro. . .3. . en cambio. .2 Una clase A se dice que es cliente de una clase B. si A contiene una declao raci´n en la que se establezca que cierta entidad (atributo. B conta. . Definici´n 2. o La figura 2. o A⇐B (a) B ↑ A (b) Figura 2. Definici´n 2. } .5 El siguiente c´digo muestra la relaci´n de clientela vista en la figura 2. .3: Otro ejemplo de Ocultaci´n de Informaci´n o o o 2. } // Acceso de lectura set { // Acceso de escritura if ( value . .3 Una clase A se dice que hereda de otra clase B. Relaciones entre clases: Cliente-Servidor y Herencia Un cliente de una clase debe ver a ´sta como un TAD. Length != 0 ) m_file_output = value .1. o bien si A es una implementaci´n de B (herencia o o de implementaci´n). // Atributo privado public string OutFile // Atributo p´ blico asociado u { get { return m_file_output .1. conocer su especificaci´n. el siguiente c´digo muestra la relaci´n de herencia mostrada en la figura o o 2.1.b se o observa la relaci´n de herencia entre dichas clases.8 Tema 2. e o pero sin importarle su implementaci´n (siempre que ´sta sea eficiente y potente). as´ como que pueda ser usada por el mayor n´mero de clientes ı u posible.1: Clientela y Herencia entre A y B Ejemplo 2. o e El creador de la clase. debe preocuparse de que dicha clase sea lo m´s reutilia zable.

Visibilidad Adem´s de lo comentado en el apartado 2. u.1. pues en ´sta ultima se puede cambiar la implementaci´n de la clase que se emplea e ´ o en el cliente. } public class Dos { public int c .4 Una clase anidada no es m´s que una clase que se declara dentro de otra y o a que tiene visibilidad sobre todas las propiedades de los objetos de la clase que la incluye. Uno u = new Uno () . Console . o o Definici´n 2.4 muestra un ejemplo de clases anidadas. return u .1. x .c = 5 + e. y = new Tres () . } public class PruebaAnidada { public static void Main () { Dos x = new Dos () . 2. se puede modificar la implementaci´n de e o B sin que esto afecte a A). Ejemplo 2. c + c .c = c = e. } public Tres y .2 acerca de la ocultaci´n de informaci´n. } private int c .1 Clases 9 Por ultimo cabe decir que la herencia es una decisi´n de dise˜o m´s comprometedora que ´ o n a la clientela. WriteLine (" IntAnidado (6) = " + IntAnidado (6) ) . sin afectar a ´ste (en nuestro ejemplo. o El resultado mostrado por pantalla ser´ ıa: IntAnidado(6) = 17 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 public class Uno { public int c .4. } } C´digo 2.2. en a o o esta secci´n trataremos la cuesti´n de las clases anidadas.6 El c´digo 2.4: Ejemplo de Clases Anidadas o . public class Tres { public int IntAnidado ( int e ) { Dos d = new Dos () . d.

3. Este objeto recibe u o el nombre de instancia actual. o Producto. el paso de par´metros es “por valor”. 2. a saber. Clases y Objetos 2. a Cuando un mensaje no especifica al objeto receptor la operaci´n se aplica sobre la instancia o actual. ´ 2. n o n El estado de un objeto viene dado por la lista de pares atributo/valor de cada campo. cada objeto se identifica un´ ıvocamente mediante su identificador de objeto (oid).2. Mientras exista. siguiendo una sintaxis como la e que a continuaci´n se muestra: o receptor.m´todo(argumentos) e 2. OO) o o existe un objeto destacado sobre el que se realiza alg´n tipo de operaci´n.2 y 2. efectuando el correspondiente paso de e par´metros.3. creada en tiempo de ejecuci´n y o o formada por tantos campos como atributos tenga la clase. o En cada instante de la ejecuci´n de una aplicaci´n Orientada a Objetos (en adelante. 2. a a o . patrones de dise˜o y GUI. Sem´ntica a La diferencia entre un mensaje y la invocaci´n a un procedimiento es que en ´ste ultimo o e ´ todos los argumentos reciben el mismo trato. Notaci´n punto o Como se ha podido observar en algunos de los ejemplos vistos hasta ahora. Dichos campos son simples si corresponden a atributos de tipos primitivos (v´ase tablas e 2. Objetos software: • Procedentes del an´lisis: objetos del dominio.10 Tema 2..9) lo que se est´ queriendo decir es que se a aplique el m´todo SetPunto sobre el objeto receptor w. a • Procedentes del dise˜o/implementaci´n: TDA’s. identificador del m´todo y los argumentos de ´ste e e ultimo. Por ejemplo.3. Una posible clasificaci´n de los objetos podr´ ser: o ıa Objetos externos: Son aquellos que existen en el dominio de la aplicaci´n. Sintaxis.SetPunto(4.5 Un objeto es una instancia de una clase. la forma en que se invoca a un m´todo es mediante el operador punto. Mensajes Los mensajes son el mecanismo b´sico de la computaci´n OO y consisten en la invocaci´n a o o de la aplicaci´n de un m´todo sobre un objeto.2. Su modificaci´n y consulta se realiza mediante mensajes. Si no se incluye nada. o e Constan de tres partes: objeto receptor. recibe un “trato especial”. Descuento. el objeto receptor.1. Para especificar un paso de a par´metros “por referencia” se emplea la palabra clave ref delante del par´metro en cuesti´n. Ejemplo 2. mientras que en los mensajes uno de esos argumentos. Objetos Definici´n 2.. mientras que se dice que son compuestos si sus valores son subobjetos o referencias. Socio. Para hacer referencia a la instancia actual en C# se emplea la palabra reservada this.6. .3.1.7 En el mensaje w. Comercial.3).

mediante los constructores e por defecto (aquellos que no tienen argumentos). o 2. la asignaci´n o no implica copia de valores sino de referencias (⇒ Aliasing). aunque tambi´n existen los tipos primitivos (figura 2. a Constituyen un soporte para definir estructuras de datos recursivas.22 ).2. Sin embargo tambi´n se pueden inicializar con unos valores por defecto.41 ) para cualquier entidad asociada a una a clase.2: Variables en los lenguajes tradicionales Figura 2. Los objetos son creados cuando son necesarios.3: Variables tipo “puntero” en los lenguajes tradicionales Figura 2. o bien ligada a un objeto (mediante el operador new. Sem´ntica referencia versus sem´ntica almacenamiento a a En C# se tiene sem´ntica referencia (figura 2. o bien no ligada (con valor null). e Toda referencia puede estar.4 Sem´ntica referencia versus sem´ntica almacenamiento a a 11 2. o si se le asigna una referencia ya ligada). 1 2 TE→Tiempo de Ejecuci´n o TC→Tiempo de Compilaci´n o . Estos constructores se encargan de inicializar los atributos con valores consistentes. Se permite la compartici´n de un objeto.4: Variables en los lenguajes OO Algunas ventajas de los tipos referencia son: Son m´s eficientes para manejar objetos. Creaci´n de objetos o En C# existe un mecanismo expl´ ıcito de creaci´n de objetos mediante la instrucci´n de o o creaci´n new y los llamados m´todos constructores (que deben tener el mismo nombre que la o e clase en la que se definen).4. Pero ojo. Figura 2. Dan soporte al polimorfismo. como ya hemos visto.5.

5). Cuando un objeto es recogido por el recolector de basura3 se llama impl´ ıcitamente a su destructor.8 El c´digo 2. e o Figura 2. } 2.1. } // Constructor int Conta { return conta .5: Ejemplo de copia superficial Definici´n 2.6: Ejemplo de copia profunda 3 garbage collector . } // Constructor por defecto Contador ( int i ) { conta = i % 100. Clases y Objetos Ejemplo 2.6). Mientras que los constructores s´ pueden tener modificadores de acceso.5: Ejemplo de Constructores o Contador () { conta = 0. Sem´ntica de la asignaci´n e igualdad entre objetos a o Definici´n 2. en la mayor´ de los casos las clases no necesitan destructores. public public public { get set } public } C´digo 2.6 Una copia se dice que es superficial si se copian los valores de cada campo o del objeto origen en el objeto destino y ambos comparten referencias (figura 2. o 2.5.6. los destructores ı carecen de ellos. 1 2 3 4 5 6 7 8 9 10 11 12 public class Contador { private int conta .12 Tema 2.7 Una copia se dice que es profunda si se crea un objeto con una estructura o id´ntica al objeto origen y sin compartici´n de referencias (figura 2. No obstante. } { conta = value % 100.5 muestra un ejemplo de una clase con un constructor y un conso tructor por defecto. Destructores Un destructor es un m´todo cuyo nombre es el nombre de la clase precedido de una tilde e ∼. pues ıa con el recolector de basura es suficiente para la finalizaci´n. Figura 2. } void Click () { conta = ( conta + 1) % 100.

m_mat [i .6 Sem´ntica de la asignaci´n e igualdad entre objetos a o 13 Como ya se dijo anteriormente. a Si se tiene sem´ntica referencia y se realiza una copia superficial. m_col = ( col <= 0 ) ? 1 : col . los cambios hechos en a una variable tienen repercusi´n en su(s) correspondiente(s) copia(s). m_mat = new double [ m_row . En C# esto se expresa de la siguiente forma: oa.Equals(ob) .9 El c´digo 2. } } C´digo 2. . i < m_row . return mat . por ejemplo. ++ j ) mat .. else m_row = row. int col ) { m_row = ( row <= 0 ) ? 1 : row . o Para evitar este efecto debemos realizar una copia profunda. mientras que si se tiene sem´ntica almacenamiento entonces se a a copian los valores.8 Dos variables se dice que son id´nticas si ambas referencian al mismo objeto o e (figura 2. e Ejemplo 2.5 y 2. j < m_col .6 muestra un ejemplo de una clase que implementa el m´todo o e Clone() de la interfaz ICloneable para conseguir una copia profunda.6 es equivalente al o siguiente c´digo: o if (row <= 0) m_row = 1.7: Ejemplo de variables id´nticas e Definici´n 2. m_col ) . la asignaci´n implica compartici´n de referencias si se o o tiene sem´ntica referencia. for ( int i = 0. } public object Clone () { matrix mat = new matrix ( m_row .7). m_col ]. public matrix ( int row . A este tipo de copia se le llama copia superficial y est´ soportada en C#.9 Dos variables se dice que son iguales si ambas referencian a objetos con o valores iguales en sus campos (figuras 2. implementando el m´todo Clone() de la interfaz ICloneable. Definici´n 2. j ] = m_mat [i . j ]. lo cual puede llevarse a cabo. En C# esto se expresa de la siguiente forma: oa == ob Figura 2. ++ i ) for ( int j = 0.7).6: Ejemplo de implementaci´n del m´todo Clone() o o e Nota.2. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class matrix : ICloneable { .La l´ ınea 6 (equivalentemente la l´ ınea 7) del c´digo 2. .

} } private DListElement next . private object data . } public DListElement ( object val . mediante el empleo de la clase ra´ ız Object. } . Next = head . a saber.5). u a C# consigue “genericidad” al estilo de Java. } } public DListElement Data { get { return data . head . Genericidad C++ hace uso de plantillas. Dichas plantillas est´n propuestas para Java y C#. 2. 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 Definici´n de una clase “Lista Doblemente Enlazada” o using System .8. para implementar clases contenedoras gen´ricas. DListElement d ) { data = val . 2.7. Imposibilidad de asegurar homogeneidad. d . } public class DList { public DList () { head = null . } set { next = value . Clases y Objetos De esta ultima definici´n se deduce que siempre que haya identidad. que son altamente eficientes y muy potentes.14 Tema 2. pero e a a´n est´n en una fase experimental. } public DList ( object val ) { head = new DListElement ( val ) . previous = this . public class DListElement { public DListElement ( object val ) { data = val . next = d . pero no necesariamente a la inversa (figura 2. } set { previous = value . Previous = null . tambi´n habr´ igual´ o e a dad superficial (figura 2. con los consabidos inconvenientes: Necesidad de conversiones expl´ ıcitas de tipo. } } public DListElement Previous { get { return previous . } set { data = value . previous .7). } public DListElement Next { get { return next .

} return h . Previous = pp . Previous = null . pp = h . h = h . DListElement np = h . return head . Next = head . Data . Previous . Next = np . } else { DListElement h = new DListElement ( val . head = h .2. Next .8 Definici´n de una clase “Lista Doblemente Enlazada” o 15 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 83 84 85 public bool IsEmpty () { return head == null . Equals ( h . if ( np != null ) np . return h . } public void Add ( object val ) { if ( IsEmpty () ) { head = new DListElement ( val ) . } } public object Front () { if ( IsEmpty () ) throw new System . Next . head . } . if ( pp != null ) pp . } public DListElement Find ( object val ) { DListElement h = head . Next . else head = null . head . Previous = h . Exception (" Empty DList ") . Data ) ) break . while ( h != null ) { if ( val . } private DListElement Delete ( DListElement h ) { if ( h == null ) return null . head ) .

16 Tema 2. } C´digo 2. } public override string ToString () { return ToStr ingRec ursive ( head ) . o e 4 Todo lo relacionado con la herencia se ver´ en profundidad en el tema 4 a . y en la l´ ınea 90 vemos c´mo se sobrescribe el m´todo heredado ToString()4 . El empleo del operador e == en esta l´ ınea provocar´ una ejecuci´n incorrecta. else return ( first . En la l´ ınea 65 vemos un ejemplo de uso del m´todo Equals. Next ) . Como se observa en la l´ ınea 23 de este c´digo los datos almacenados en la lista son de o tipo object. o Otro ejemplo de ocultaci´n de informaci´n es la declaraci´n como privados de los m´too o o e dos Delete y ToStringRecursive de las l´ ıneas 72 y 93. } private DListElement head . } static string To String Recursive ( DListElement first ) { if ( first == null ) return "". Es este un ejemplo de ocultaci´n de o informaci´n. Clases y Objetos 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 public DListElement Delete ( object v ) { return Delete ( Find ( v ) ) . ıa o En la l´ ınea 55 se ve un ejemplo del uso de excepciones. as´ como la sobrecarga de constructores en las l´ ı ıneas 4 y 6.7: Lista gen´rica doblemente enlazada o e A continuaci´n destacaremos algunos aspectos de este c´digo: o o Obs´rvese el uso de get y set en las l´ e ıneas 13 a 20 (en m´todos declarados como p´blicos) e u y las declaraciones privadas de las l´ ıneas 22 y 23. Data + "\ n ") + ToStr ingRec ursive ( first . respectivamente. las cuales trataremos en el siguiente tema. as´ es como se consigue “genericidad” en ı C#. distinta a la esperada. respectivamente. Podemos ver la implementaci´n de un constructor por defecto y un constructor en las o l´ ıneas 28 y 29. Como ya se dijo anteriormente.

sin embargo permite al programador intentar recuperarse frente a estas situaciones y as´ continuar con la ejecuci´n del programa. Si esto es as´ se dice a ı.1 En el c´digo 3. o ıan En C# la clase Debug contiene el m´todo Assert(). siempre que la entrada sea correcta. con el mensaje mensaje. Seg´n este modelo. por su parte.1 se muestra un ejemplo del uso de asertos. Contrato software Desde un punto de vista una excepci´n se puede decir que se basa en el incumplimiento o del contrato software entre el cliente y el servidor de una clase. C#. la ejecuci´n proporciona una o o u o salida de diagn´stico. no se lleva a cabo en la mayor´ de las ocasiones. el usuario (cliente) debe garantizar que se cumplen las condiciones u necesarias para una correcta aplicaci´n del software. o Ejemplo 3. a Establecer una prueba formal completa de correcci´n del software es algo muy deseable.1. o Si la expresi´n expresi´n booleana se eval´a como falsa. el software realizar´ la tarea deseada satisfactoriamente. El proveedor (servidor). A estas condiciones se le conocen como o precondiciones. o pero por desgracia. o 17 . De hecho. ı o 3. debe garantizar que. invocado de la siguiente manera: e Assert(expresi´n booleana. que se cumplen las postcondiciones.2.mensaje). as´ como del empleo o ı de listeners para visualizar los mensajes de diagn´stico por pantalla. 3. con un mensaje de error. Clases y Correcci´n del software: Asertos o La correcci´n de los programas se puede ver en parte como una prueba de que la ejecuci´n o o terminar´ proporcionando una salida correcta. Las excepciones son habitualmente condiciones inesperadas de error que provocan la finalizaci´n del programa en el que o tienen lugar.Tema 3 Dise˜ o por Contrato: Asertos y n Excepciones En este tema se describe el manejo de excepciones en C#. si el cliente cumple con las precondiciones. Los asertos se habilitan definiendo la variable o DEBUG. la discipliıa na consistente en plantear asertos apropiados frecuentemente consigue que el programador advierta y evite bastantes errores de programaci´n que antes podr´ pasar desapercibidos. Para acceder a dicha salida de diagn´stico se emplean los listener.

o El mecanismo de manejo de excepciones en C# es sensible al contexto.3. double x . WriteLine (" Introduzca un n´ mero real positivo :") . El inconveniente de los asertos es que no permiten una estrategia ıa a de reparaci´n o reintento para continuar con la ejecuci´n “normal” del programa. Y dicho contexto no es m´s que un bloque try. Console . Dise˜ o por Contrato: Asertos y Excepciones n 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # define DEBUG using System .Exception. public class LanzaExcepcion { public static void Main () { try { double x .1: Ejemplo del uso de asertos o El uso de asertos reemplaza el uso ad hoc de comprobaciones condicionales con una metodolog´ m´s uniforme. x = double . Excepciones en C# C# contiene la clase est´ndar System. Clear () . en el cual se declaran los manejadores (handlers) al final del a mismo mediante la palabra clave catch. Parse ( datos ) . o la expresi´n throw y los manejadores definidos mediante la palabra clave catch. Ejemplo 3. que es el objeto o la clase base de un a objeto lanzado por el sistema o por el usuario cuando ocurre un error en tiempo de ejecuci´n. ı } } C´digo 3. u datos = Console . o 1 2 3 4 5 6 7 8 using System .2 muestra un ejemplo del uso de excepciones. Diagnostics . Un c´digo de C# puede alcanzar una excepci´n en un bloque try mediante la expresi´n o o o throw. Console . o o 3. " Valor no positivo ") . string datos . string datos . WriteLine (" La ra´ z cuadrada es " + Math .2 El c´digo 3. Debug . public class AssertSqrRoot { public static void Main () { Debug . Add ( new T e x t W r i t e rT r ac eL i st e ne r ( Console .18 Tema 3. Console . using System . Listeners . . Out ) ) . Assert ( x > 0 . La excepci´n es entonces tratada por alguno de los manejadores que se encuentran al o final del bloque try. Listeners . readLine () . WriteLine ( x ) . con un bloque try. Sqrt ( x ) ) . Debug .

3. Parse ( datos ) . x = double . datos = Console . WriteLine ( x ) . Console . WriteLine (" Lanzada excepci´ n " + e ) .IO para las excepciones de E/S Intento de referenciar a null Ejecuci´n fuera de la memoria heap o (mont´n) o Tabla 3. Sqrt ( x ) ) .1 muestra algunas excepciones est´ndar en C#. if ( x > 0) throw ( new System . Exception () ) .2: Propiedades de las excepciones . WriteLine (" La ra´ z cuadrada es " ı + Math . } catch ( Exception e ) { Console . mientras que en la tabla 3.2 a podemos observar las propiedades est´ndar que toda excepci´n debe tener. readLine () .1: Algunas Excepciones est´ndar a HelpLink InnerException Message StackTrace Source TargetSize Obtiene o establece un enlace a un fichero de ayuda Obtiene la instancia de Exception que caus´ la excepci´n o o Texto que describe el significado de la excepci´n o Traza de la pila cuando se llam´ a o la excepci´n o Aplicaci´n u objeto que gener´ la o o excepci´n o M´todo que lanz´ la excepci´n e o o Tabla 3. WriteLine (" Introduzca un double :") . } o } } C´digo 3.3 Excepciones en C# 19 9 10 11 12 13 14 15 16 17 18 19 20 21 Console . else Console . a o SystemException ApplicationException ArgumentException ArgumentNullException ArgumentOutOfRangeException ArithmeticException DivideByZeroException IndexOutOfRangeException InvalidCastException IOException NullReferenceException OutOfMemoryException Clase base para las excepciones del sistema Clase base para que los usuarios proporcionen errores de aplicaci´n o Uno o m´s argumentos son inv´lidos a a Pasado null no permitido Fuera de los valores permitidos Valor infinito o no representable Auto-explicativa ´ Indice fuera de los l´ ımites del array Cast no permitido Clase base en el espacio de nombres System.2: Ejemplo del uso de excepciones o La tabla 3.

el lanzamiento de una excepci´n pasa cierta informaci´n a los manejao o dores. Por ejemplo. LanzaMsg () . . el usuario probablemente querr´ informaci´n adicional por pantalla para a o seleccionar o ayudarle a decidir la acci´n a realizar por el manejador. // Relanzamiento } } public static void Main () { try { . a o Si lo que queremos es relanzar la excepci´n actual podemos emplear un throw sin arguo mentos en el cuerpo de un catch. . . . . WriteLine (" Excepci´ n recapturada " + e ) . . las cuales deben ser objetos de la o clase Exception. throw . pero con frecuencia ´stos no precisa de dicha informaci´n. Esta situaci´n puede ser util si deseamos que un segundo o ´ manejador llamado desde el primero realice un procesamiento m´s exhaustivo de la excepci´n a o en cuesti´n. } catch ( Exception e ) { . .20 Tema 3. un manejador e o que simplemente imprime un mensaje y aborta la ejecuci´n no necesita m´s informaci´n de o a o su entorno. Console . . } catch ( Exception e ) { Console . public class ReLanzaExcepcion { public static void LanzaMsg () { try { .3 El c´digo 3. throw new Exception (" Lanzada en LanzaMsg ") . . En este caso ser´ o ıa apropiado “empaquetar” la informaci´n en un objeto derivado de una clase Exception ya o existente. o Ejemplo 3.1. El bloque try m´s interno en el que se lanza una excepci´n es empleado a o para seleccionar la sentencia catch que procesar´ dicha excepci´n. } o } } C´digo 3. .3. .3: Ejemplo del relanzamiento de excepciones o Conceptualmente. o 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 using System . Lanzamiento de excepciones Mediante la expresi´n throw se lanzan excepciones.3 muestra un ejemplo del relanzamiento de excepciones. Sin embargo. Dise˜ o por Contrato: Asertos y Excepciones n 3. . . WriteLine (" Primera captura " + e ) .

" Out of bounds ") . } catch ( StackError se ) { Console .3 Excepciones en C# 21 Ejemplo 3. } get { return msg . stk . o El resultado mostrado por pantalla ser´ algo como: ıa Out of bounds with last char z 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 using System .2. try { throw new StackError ( stk . private string msg .3.4: Uso de excepciones con m´s informaci´n o a o 3. } public class StackErrorTest { public static void Main () { Stack stk = new Stack . public class Stack { public char [] s = new char [100]. s [99]. El orden en el que se definen los manejadores determina el orden en el que se intenta invocar cada manejador que puede tratar la excepci´n que haya saltado. string message ) { st = s . } public string Msg { set { msg = value . . } public char TopEntry () { return st .4 muestra un ejemplo del uso de objetos para empaquetar inforo maci´n que se pasa a los manejadores de excepciones. } } } C´digo 3. Si la excepci´n lanzada ha sido derivada de la clase base del manejador.4 El c´digo 3. o Una excepci´n puede ser tratada por una manejador en concreto si se cumplen alguna de o estas condiciones: 1. Si hay una coincidencia exacta. WriteLine ( se . como muestra el siguiente ejemplo. s [99] = ’z ’. 2. Bloques try Un bloque try es el contexto para decidir qu´ manejador invocar para cada excepci´n e o que se dispara. } public class StackError : Exception { public StackError ( Stack s .3. Msg + " with last char " + se . o Es un error listar los manejadores en un orden en el que se impida la ejecuci´n de alguno o de ellos. TopEntry () ) . }} private Stack st . msg = message .

Error . o Los asertos simplemente imprimen un mensaje por pantalla. Incluso existe un catch sin ning´n argumento. se puede decidir (en algunos casos) entre a a o continuar la ejecuci´n del programa o abortarla de inmediato.22 Tema 3. Conversi´n de asertos en excepciones o La l´gica de las excepciones es m´s din´mica ya que los manejadores pueden recibir m´s o a a a informaci´n que los asertos. string datos . . string message .5 es una reescritura del c´digo 3.3. como ya hemos visto anteriormente. throw e . Exception e ) { if (! cond ) { Console . Manejadores La sentencia catch parece la declaraci´n de un m´todo con un solo argumento y sin valor o e de retorno. adem´s de imprimir m´s informaci´n. mientras que con las excepciones.1 que se muestra en el ejemplo o o 3. o Ejemplo 3. La palabra clave finally despu´s de un bloque try introduce otro bloque que se ejecuta e despu´s del bloque try independientemente de si se ha lanzado una excepci´n o no.3. el cual maneja las excepciones no u tratadas por los manejadores que s´ tienen argumento. WriteLine (" Introduzca un double positivo :") . public class ExAssert { public static void MyAssert ( bool cond . } } } class ExceptionSqrRoot { public static void ConsoleSqrt () { double x .5 Seg´n el siguiente c´digo: u o catch(ErrorClaseBase e) catch(ErrorClaseDerivada e) nunca se ejecutar´ el cuerpo del segundo catch.1 del uso de asertos. WriteLine ( message ) . En este ejemplo se ve c´mo el programa hace uso del mecanismo de excepciones para o llamarse a s´ mismo recursivamente hasta que el usuario introduzca un n´mero v´lido para ı u a la entrada. nos salimos del bloque e o try y autom´ticamente se llama a los m´todos (incluidos los destructores) que liberan la a e memoria ocupada por todos los objetos locales al bloque try. e o 3. Dise˜ o por Contrato: Asertos y Excepciones n Ejemplo 3. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 using System . pues antes se encontrar´ una coincidencia ıa ıa con el primer catch. Console . seg´n lo dicho en las condiciones anteriores.4. pero ahora mediante excepciones. ı Cuando se invoca a un manejador a trav´s de una expresi´n throw. u 3.6 El c´digo 3.

WriteLine ( x ) . readLine () . WriteLine (" La ra´ z cuadrada es " + Math .5: Ejemplo del uso de excepciones en vez de asertos o . " Valor no positivo : x = " + x . x = double . WriteLine (" Probando Ra´ ces Cuadradas ") . new Exception () ) . // Se vuelve a intentar } } public static void Main () { Console . } catch ( Exception e ) { Console .3. Console .4 Conversi´n de asertos en excepciones o 23 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 datos = Console . Parse ( datos ) . ExceptionSqrRoot . WriteLine ( e ) . Console . ConsoleSqrt () . ToString () . Sqrt ( x ı )). } } C´digo 3. try { ExAssert . MyAssert ( x > 0 . ı ConsoleSqrt () .

Dise˜ o por Contrato: Asertos y Excepciones n .24 Tema 3.

e 25 .1: Jerarqu´ de clases ıa Definici´n 4. ıa Figura 4. as´ como los privilegios de acceso.1. e ı Ejemplo 4. Introducci´n o La herencia es un potente mecanismo para conseguir reutilizaci´n en el c´digo.1 Si B hereda de A entonces B incorpora la estructura (atributos) y comporo tamiento (m´todos) de A. Una clase derivada hereda la deso cripci´n de la clase base. pero puede incluir adaptaciones: e B puede a˜adir nuevos atributos. A trav´s de la herencia es posible e crear una jerarqu´ de clases relacionadas que compartan c´digo y/o interfaces.Tema 4 Herencia 4. la cual se puede alterar a˜adiendo nuevos miembros y/o modificando o n los m´todos existentes. o B puede implementar un m´todo diferido en A. consistente o o en derivar una nueva clase a partir de una ya existente. bien para e e mejorar la implementaci´n). n e B puede redefinir m´todos de A (bien para extender el m´todo original.1 En la figura 4. n B puede a˜adir nuevos m´todos. ıa o En muchas ocasiones distintas clases resultan ser variantes unas de otras y es bastante tedioso tener que escribir el mismo c´digo para cada una.1 se muestra un ejemplo de una jerarqu´ de clases.

o a Ejemplo 4. Doble aspecto de la herencia Como ya se dijo en la definici´n 2.a y 4. o Por otra parte. o Figura 4.1. o o Esto es.2. una clase B puede heredar de otra clase A.1: Propiedades de las excepciones 4. Sin o embargo.2: Herencia de especializaci´n y de implementaci´n o o 4.3. as´ como en las figuras ı 4.2 La herencia entre clases que se observa en la figura 4. lo cual quiere decir que sus entidades (las cuales poseen un unico tipo est´tico y un conjunto de tipos din´micos) pueden estar conectadas a una instancia ´ a a de la clase asociada en su declaraci´n o de cualquiera de sus subclases. si no. o Podr´ ıamos categorizar el polimorfismo en dos tipos: Param´trico e Real y Aparente → Sobrecarga Inclusi´n (basado en la herencia) o . ra´ en toda e u ız jerarqu´ de clases de C#.2. Herencia La tabla 4.d muestran la herencia como mecanismo de implementaci´n.2 Podr´ o ıamos definir el polimorfismo como la capacidad que tiene una entidad para referenciar en tiempo de ejecuci´n a instancias de diferentes clases. por ser B una especializaci´n de A. a la vez.1 muestra los m´todos p´blicos y protegidos de la clase object. devuelve false Equivalente a escribir un destructor Proporciona un entero unico para ´ cada objeto Permite averiguar din´micamente el a tipo de objeto Permite clonar un objeto Devuelve true si los objetos son la misma instancia Devuelve un string que representa al objeto actual Tabla 4. la herencia es.c y 4. object b) string ToString() Devuelve true si dos objetos son equivalentes.26 Tema 4. ıa bool Equals(object o) void Finalize() int GetHashCode() Type GetType() object MemberwiseClone() bool ReferenceEquals (object a.2.b sirve como mecanismo de especializaci´n. m´s refinada) de A. los ejemplos de las figuras 4.2. puede ocurrir que el motivo por el cual B hereda de A sea la necesidad de construir una implementaci´n “distinta” (si se quiere.3. o C# soporta el polimorfismo. Polimorfismo Definici´n 4.2. un mecanismo de especialio zaci´n y un mecanismo de implementaci´n.

3. Pero no lo ser´ ıan.1. N´tese que el operador de asignaci´n no puede o o sobrecargarse y que los operadores sobrecargados mantienen la precedencia y asociatividad de los operandos. hasta una suma entera. a u La tabla 4. podemos decir que: te(p) = Poligono ctd(p) = {Poligono. Triangulo t.3 La sobrecarga consiste en dar distintos significados a un mismo m´todo u o e operador. todo ello depenu diendo del tipo de datos de a y b. tambi´n es sobrecargado impl´ e ıcitamente. si a y b son de tipo o o string. + − ! ∼ ++ −− true f alse Tabla 4.3 Dada la siguiente declaraci´n. Rectangulo r.2: Operadores unarios “sobrecargables” + − ∗ / % & | ∧ << >> == ! = < > >= <= Tabla 4. C# soporta la sobrecarga de m´todos y de operadores. Tanto los operadores binarios como los unarios s´lo pueden ser sobrecargados mediante o m´todos est´ticos. o ‘+=’. Sin embargo. o ıa Poligono p. r = p. >. r = c. en el caso de los operadores relacionales <. Cuadrado} te(c) = Cuadrado ctd(c) = {Cuadrado} donde “te” significa “tipo est´tico” y “ctd” significa “conjunto de tipos din´micos”. en punto flotante o de n´meros complejos. Ejemplo 4. e a .3 Polimorfismo 27 Ejemplo 4.1.4. p = r. mientras que la tabla 4. a a Y por lo tanto las siguientes asignaciones ser´ v´lidas: ıan a p = t. lo realmente interesante es poder redefinir operadores cuyos operandos sean de tipos definidos por el usuario. Rectangulo. p = c. Cuadrado} te(t) = Triangulo ctd(t) = {Triangulo} te(r) = Rectangulo ctd(r) = {Rectangulo. Cuadrado c. su operador de asignaci´n asociado.3: Operadores binarios “sobrecargables” Cuando se sobrecarga un operador tal como ‘+’. por ejemplo: 4.2 muestra los operadores unarios que en C# se pueden sobrecargar. Pero conviene tener en cuenta que este tipo de actuaci´n s´lo es provechosa en aquellos o o casos en los que existe una notaci´n ampliamente usada que conforme con nuestra sobrecarga o (m´s a´n. y C# permite hacer esto. si cabe. Uno de los ejemplos m´s claros es e a el del operador ‘+’. c = t. siguiendo la jerarqu´ de clases de la figura 4.3 hace lo propio con los operadores binarios. c = p. Sobrecarga Definici´n 4.4 La expresi´n a + b puede significar desde concatenaci´n. Triangulo. <= y >=). t = r.

} public void Tick () { Reset (++ totSecs ) . Esta pr´ctica com´n a a u evita que el operador sobrecargado tenga un orden prefijado en sus operandos. } public static MyClock operator +( MyClock c1 . El resultado mostrado por pantalla tras ejecutarse el m´todo Main() ser´ e ıa: Initial times day 00 time:00:00:59 day 01 time:23:59:59 One second later day 00 time:00:01:00 day 02 time 00:00:00 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 System . Tick () . } public static MyClock operator ++( MyClock c ) { c . } . } public static MyClock operator *( uint m . mins = 0 . o como binarios. pero con los par´metros en orden inverso. uint m ) { return ( m * c ) . return c . } private uint totSecs = 0 . totSecs ) . } public override string ToString () { Reset ( totSecs ) . totSecs ) . hours . Herencia Ejemplo 4. mins = ( i / 60) % 60. days = 0.1 muestra un ejemplo de sobrecarga de operadores.28 Tema 4. mins . MyClock c2 ) { return new MyClock ( c1 . return String . MyClock c ) { return new MyClock ( m * c . tanto unarios. previamente sobrecargado por el m´todo de la l´ e ınea 29. secs = 0 . Format (" day {0: D2 } time :{1: D2 }:{2: D2 }:{3: D2 }" . class MyClock { public MyClock () { } public MyClock ( unit i ) { Reset ( i ) . days . } public static MyClock operator *( MyClock c . days = i / 86400. secs = i % 60. } public void Reset ( unit i ) { totSecs = i .5 El c´digo 4. Obs´rvese como en la l´ e ınea 32 se vuelve a definir el operador ‘*’. hours = 0 . secs ) . hours = ( i / 3600) % 24. totSecs + c2 .

. Definici´n 4.7 es un claro ejemplo de eso tructura de datos polimorfa. a 4. WriteLine (" Initial times \ n " + a + ’\n ’ + b ) .2. cuya sintaxis es expresi´n is tipo.. Y r est´ disponible para la clase que incluye el mensaje.4..). Console . devuelve true si se puede hacer un o “cast” de la expresi´n expresi´n al tipo tipo. ++ b .. o o El operador as.. Definici´n 4. Operadores is y as El operador is. 2.) a una rutina r(. Figura 4. Si en la l´ ınea 23 de dicho c´digo en vez de poner private object data escribi´ramos o e private Figura data. } } C´digo 4. supuesta la declaraci´n X x. o a 1 2 En adelante. a u 3. b = new MyClock (172799) . RA En adelante. o bien.3. Los argumentos son compatibles con los par´metros y coinciden en n´mero.3.y.1.5 Regla de la Asignaci´n 1 o o Una asignaci´n x = y o una invocaci´n r(. X incluye una propiedad con nombre final r. ser´ legal si: o a 1.3 Polimorfismo 29 37 38 39 40 41 42 43 44 45 class MyClockTest { public static void Main () { MyClock a = new MyClock (59) . siguiendo el ejemplo de jerarqu´ de clases de la figura 4. Estructuras de datos polim´rficas o La lista doblemente enlazada implementada en el c´digo 2.3.1: Ejemplo de Sobrecarga de Operadores o 4.. si la conversi´n no est´ permitida. Console .4. RVM . ser´ legal o o a si el tipo de y es compatible con el tipo de x.r(y). Regla de aplicaci´n de propiedades o Definici´n 4..3: Ejemplo de estructura de datos polimorfa 4..T x.3. si la clase de T1 es la misma o que la de T2 o una subclase de T2.6 Regla de Validez de un Mensaje 2 o Un mensaje ox. ++ a .4 Un tipo T1 es compatible con otro tipo T2. WriteLine (" One second later \ n " + a + ’\n ’ + b ) . devuelve null. con id´ntica sintaxis devuelve la expresi´n expresi´n convertida al tipo e o o tipo. en un ıa instante dado podr´ ıamos tener una lista como la que se observa en la figura 4.3.

Los m´todos o e e e sobrecargados son seleccionados en tiempo de compilaci´n bas´ndonos en sus prototipos o a (argumentos y valor de retorno) y pueden tener distintos valores de retorno.30 Tema 4. e N´tese la diferencia entre un m´todo redefinido y un m´todo sobrecargado.f → δ En C#. Un m´todo redefinido. Herencia 4. como en C++. oa.4: Herencia y redefinici´n de m´todos o e Dadas las siguientes declaraciones: A oa. void. as´ como de la palabra clave ı override en la l´ ınea 9. siendo necesario incluir la a palabra clave virtual en aquellos m´todos que vayan a ser redefinidos y a los cuales s´ se e ı aplicar´ ligadura din´mica.f → β oa = oc. oa. e Ejemplo 4. El resultado mostrado por pantalla tras ejecutarse el m´todo Main() ser´ e ıa: Dentro de la clase base Dentro de la clase derivada Dentro de la clase derivada .7 El c´digo 4. e e Entonces cuando tengamos un objeto de la clase A y una invocaci´n a un m´todo redeo e finido en la clase B. a saber.4 se muestra una jerarqu´ de clases en las que algunas de ellas ıa redefinen el m´todo f de sus ancestras. Obs´rvese el uso de la palabra clave virtual en la l´ e ınea 4.6 En la figura 4. como ya hemos visto en varios a ejemplos con el m´todo ToString(). la ligadura es est´tica por defecto. C oc = new C(). si una clase B hereda de otra clase A. D od = new D().2 muestra un ejemplo de redefinici´n de un m´todo heredado de la o o e clase base. oa. Ligadura Din´mica a Como ya dijimos en la definici´n 4. la versi´n del m´todo que se ejecute depender´ del tipo din´mico del o e a a objeto de la clase A.4. din´mico del objeto oa: a oa = ob. A continuaci´n se muestra qu´ versi´n del m´todo f se ejecutar´ dependiendo del tipo o e o e ıa. Las letras griegas representan la versi´n de cada e o m´todo. e Figura 4. por contra.1. es seleccionado en tiempo de ejecuci´n bas´ndonos en e o a el tipo din´mico del objeto receptor y no puede tener distinto valor de retorno del que tenga a el m´todo al que redefine. B ob = new B(). B puede o redefinir m´todos de A e implementar m´todos que en A sean diferidos. a a Aquellas subclases que quieran redefinir un m´todo declarado como virtual en la clase e base deber´n emplear para ello la palabra clave override.f → α oa = od. Obs´rvese tambi´n como el valor devuelto por el m´todo redefinido e e e de la l´ ınea 9 es el mismo que el del m´todo original de la l´ e ınea 4. En esto consiste la ligadura din´mica. a Ejemplo 4.

7 Una clase diferida o abstracta es aquella que contiene m´todos abstractos. b . Ejemplo 4. Si una clase hereda de otra clase abstracta y no implementa todos sus m´todos abstractos.2: Redifinici´n de un m´todo heredado o o e 4.8). } . e entonces sigue siendo abstracta. Clases Diferidas Definici´n 4. } } class ClaseDerivada : ClaseBase { public override void Status () { Console .4. abstract public double Perimetro () . Status () . Status () . Para declarar en C# un m´todo como abstracto se emplea la palabra clave abstract. WriteLine (" Dentro de la clase base ") . WriteLine (" Dentro de la clase derivada ") . o e esto es. es a parcialmente abstracta (ver definici´n 4.5. Es por ello que la subclase Triangulo sigue siendo abstracta. cuyo m´todo o e abstracto Area() es implementado en las subclases Rectangulo y Circulo. ClaseDerivada d = new ClaseDerivada () . } } C´digo 4. No se pueden crear instancias e de una clase abstracta. pero no en la subclase Triangulo. Status () . y e para implementarlo en alguna subclase utilizamos la palabra clave override. o Sin embargo el m´todo abstracto Perimetro() es implementado en las tres subclases. Para ser m´s preciso. b . class ClaseBase { public virtual void Status () { Console .8 El c´digo 4. m´todos que deben ser implementados en las subclases. abstract class Figura { abstract public double Area () . d . } } class L i g a d u r a D i n a m i c a T e s t { public static void Main () { ClaseBase b = new ClaseBase () .5 Clases Diferidas 31 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 . e 1 2 3 4 5 6 using System . b = d.3 muestra un ejemplo de una clase abstracta Figura.

Por lo tanto las palabras clave abstract y public se pueden omitir. s´lo m´todos. 4. } private double lado1 . } private double radio . sin embargo.1. } public override double Area () { return ( Math .32 Tema 4. } class Circulo : Figura { public Circulo ( double r ) { radio = r . } abstract class Triangulo : Figura { public Triangulo ( double l1 . } public override double Perimetro () { return ( lado1 + lado2 + lado3 ) . Para referenciar al constructor de la clase base a˜adimos al final del constructor de la n clase derivada lo siguiente: : base(argumentos). lado3 = l3 .3: Clase abstracta Figura o Definici´n 4. Herencia 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 class Rectangulo : Figura { public Rectangulo ( double a . mientras que en C# a o ´ est´ permitida la herencia m´ltiple de interfaces3 . adem´s de ser abstractos como ya hemos dicho. PI * radio * radio ) . double b ) { altura = a . double l3 ) { lado1 = l1 . PI * radio * 2) .5. u Para declarar una interface se emplea la palabra clave interface. pues una clase abstracta puede estar parcialmente implementada. } C´digo 4. Pero no confundamos. lado2 . } public override double Perimetro () { return ( Math . lado2 = l2 . o e 3 Lo veremos en profundidad m´s adelante a . deben e a ser p´blicos. Interfaces Definici´n 4.9 Una clase que unicamente contiene m´todos abstractos recibe el nombre de o ´ e interface. base . lado3 . no puede contener miembros de datos. double l2 . } public override double Area () { return ( base * altura ) . Adem´s una clase s´lo puede heredar de una unica clase abstracta. o Una interface puede heredar de otra interface. a u Todos los m´todos de una interface.8 Una clase parcialmente abstracta es aquella que contiene m´todos abstractos o e y efectivos. } private double altura . no es lo mismo que una clase abstracta. base = b . El constructor de la clase base es invocado antes de ejecutar el constructor de la clase derivada. y para implementar una interface se emplea la notaci´n vista hasta ahora para la herencia. } public override double Perimetro () { return (( base * 2) + ( altura * 2) ) .

} // N o seguridad social } class Ayudante : IPersona . set . Las tres son implementadas por la clase Ayudante. } // M´ todos y propiedades requeridos por IEstudiante e public double NotaMedia { get { return notaMedia . IEstudiante . set . } set { edad = value . } int A~ oMatricula { get . IProfesor { // M´ todos y propiedades requeridos por IPersona e public string Name { get { return name . } int Edad { get . set . set .4. } set { telefono = value . } set { a~ oMatricula = value .5: Herencia e implementaci´n de interfaces o 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 interface IPersona { string Nombre { get . } bool esMayorDeEdad () .9 En el c´digo 4. set . } set { name = value .4 se muestra un ejemplo de una interface IPersona.5 Clases Diferidas 33 Ejemplo 4. } n } interface IProfesor : IPersona { double Salario { get . set . } } public int Edad { get { return edad . } set { notaMedia = value . a diferencia de las clases. La figura 4. } string Nss { get . que no la llevan. } } public string Telefono { get { return telefono . Obs´rvese el convenio de nombrar a las interfaces con una ‘I’ may´scula delante del e u nombre. } } public int A~ oMatricula n { get { return a~ oMatricula . set .5 muestra el esquema de herencia e implementaci´n de las interfaces y la clase o en cuesti´n. } string Telefono { get . } interface IEstudiante : IPersona { double NotaMedia { get . de la cual o heredan otras dos interfaces IEstudiante e IProfesor. n n } } . o Figura 4. } } public bool esMayorDeEdad () { return ( edad >= 18) .

int edad . Format (" Nombre : {0: -20} Tel´ fono : {1 . a~ oMatricula ) . string numSec ) { nombre = nom . nss . Herencia 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 // M´ todos y propiedades requeridos por IProfesor e public double Salario { get { return salario . telefono . 3. Conseguida gracias a la ligadura din´mica y el o a polimorfismo. double sal . o 2. edad = ed . a~ oMatricula = am . double nm .4: Herencia M´ltiple mediante interfaces o u string nombre . Conseguida gracias a la ligadura din´mio a ca y el polimorfismo. salario . reutilizaci´n y extensibilidad del software o A continuaci´n enumeramos cu´les son los requerimientos que debe cumplir un m´dulo o a o para facilitar la reutilizaci´n: o 1.. Variaci´n en tipos. nss = numSec .9} Edad : {2 . Independencia de la representaci´n. notaMedia . n salario = sal . string tlf . . Herencia. string telefono . n o nombre . int a~ oMatricula . telefono = tlf .2}" + e "\ nSeguridad Social : {3} Salario : {4: C }" + "\ nNota media : {5} A~ o de matriculaci´ n : {6}" .. int ed . Conseguida gracias a la genericidad. public override ToString () { return String . edad . n double salario . notaMedia = nm . double notaMedia . } } public string Nss { get { return nss . } } // Constructores para Ayudante public Ayudante ( string nom . n } private private private private private private private } C´digo 4. } set { salario = value .34 Tema 4. 4. } // Otras implementaciones de constructores y m´ todos e .6. } set { nss = value . string nss . int am . Variaci´n en estructuras de datos y algoritmos.

Conseguida mediante la construcci´n de clases. Agrupaci´n de rutinas relacionadas. o Para ello la interface IEnumerable declara el m´todo IEnumerator GetEnumerator(). Obs´rvese que este valor no puede ser modificado. cuya sintaxis es: e o foreach (Tipo nombreVariable in nombreArray) Mediante la instrucci´n foreach tenemos en cada iteraci´n en la variable nombreVariable o o el contenido de la clase contenedora.5 muestra un ejemplo de una clase que implementa la interface o IEnumerable. para realizar una implementaci´n concreta deben implementarse (valga la reo dundancia) los m´todos MoveNext() y Reset(). Noo u sotros trataremos ahora brevemente el contenido de System.). Para construir un iterador necesitamos alguna manera de avanzar el iterador. o En C# existe una gran colecci´n (a´n en crecimiento) de elementos reutilizables.IEnumerable. using System . Captura de similitudes entre un un subgrupo de un conjunto de posibles implementaciones.10 El c´digo 4. } set { a [ i ] = value . 3 7 11 15 19 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 using System . la segunda la 1. la creaci´n o o o de componentes reutilizables. Collections . Se trata de un array de 10 enteros cuyo iterador s´lo indexa los elementos que ocupan o posiciones impares (teniendo en cuenta que la primera posici´n es la 0. reutilizaci´n y extensibilidad del software o 35 4. o o Existen dos aspectos importantes en la reutilizaci´n de c´digo: por una parte. la utilizaci´n de dichos componentes.. y por otra parte. Ejemplo 4. class ArrayImpar : IEnumerable { public int [] a = new int [10].Collections y la interface Collections... devolver el siguiente valor en la colecci´n y comprobar en cada instante si ya hemos iterado sobre todos o los elementos de la colecci´n.. Conseguida gracias a la herencia. 5. } public int this [ int i ] { get { return a [ i ]. public IEnumerator GetEnumerator () { return ( IEnumerator ) new ArrayImparEnumerator ( this ) . La implementaci´n de la interface IEnumerate por parte de una clase contenedora dota o a ´sta de la posibilidad de emplear la instrucci´n foreach. as´ como el m´todo de acceso Current. todos e ı e ellos de la interface IEnumerator. de modo que se podr´ emplear la instrucci´n foreach con objetos de dicha a o clase (como puede observarse en la l´ ınea ). o El resultado mostrado por pantalla ser´ ıa: 1 3 5 7 9 11 13 15 17 19 Iterando. e No obstante. } } private class A r r a y I m p a r E n umerator : IEnumerator { public A r r a y I m p a r E n u m e r ator ( ArrayImpar a ) .6 Herencia.4. . s´lo e o puede consultarse.

Write ( ai . } } C´digo 4. a = a . Console . Una a o a propiedad con este modificador de acceso s´lo puede ser accedida desde c´digo perteneciente o o al mismo ensamblado en el que se haya definido dicha propiedad. Herencia 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 46 47 48 { this . Este tipo de ı clases. return ( indice <= 9) . llamadas selladas. a [ i ] + " ") . indice = -1.1. i < 10. La herencia privada. a [ i ] = 2 * i + 1. i ++) { ai . } publoc object Current { get { return a [ indice ]. no es soportada en C#. pues puede ocurrir que una subclase apoye algunos de sus m´todos en la implementaci´n concreta e o conocida de la clase base. todas sus subclases que hayan actuado de la manera anteriormente indicada se ver´n afectadas y a probablemente tambi´n deber´n modificar su implementaci´n.. e a o Adem´s de los tres tipos de acceso vistos en la secci´n 2. } } private int indice .") .36 Tema 4. . foreach ( int elemento in ai ) Console . } public bool MoveNext () { indice += 2. } public void Reset () { indice = -1. WriteLine ("\ nIterando . } class ArrayImparTest { public static void Main () { ArrayImpar ai = new ArrayImpar () .. ya que sus m´todos no pueden ser redefinidos y por tanto se declaran autom´ticamente e a como no virtuales. } Console . Write ( elemento + " ") . a s´ se puede inhabilitar la herencia de una clase mediante la palabra clave sealed. private ArrayImpar a . Sin embargo. pues si modificamos la clase base. for ( int i = 0. que est´ permitida en C++.5: Implementaci´n de un iterador o o Tratando ahora la cuesti´n referente a la ocultaci´n de informaci´n en los casos en los o o o que existe herencia diremos que en tales situaciones se viola el principio de caja negra. ´ Este es un factor negativo para la extensibilidad.2 existe otro m´s: internal. pueden ser tratadas de una forma m´s eficiente por parte del compia lador.

Sin ema u bargo.7 se muestra un ejemplo de colisi´n de nombres debida a la o herencia m´ltiple. a .6: Herencia simple y m´ltiple u En C#.13 En la figura 4.(a) muestra un ejemplo de herencia simple.4 as´ como en la figura 4. tambi´n implica algunos inconvenientes. e ´ a La colisi´n de nombres tiene lugar cuando una clase hereda de dos o m´s clases un o a m´todo con el mismo nombre y diferente implementaci´n. como veremos m´s adelante.7. a diferencia de C++. ıa e A continuaci´n explicaremos dos de ellos: la colisi´n de nombres y la herencia repetida o o (aunque ´sta ultima. mientras que la figura 4.4.7 Herencia m´ ltiple u 37 4. al igual que en Java. no se da en C#).1.7. a Ejemplo 4. Herencia m´ ltiple u Definici´n 4. e o Ejemplo 4. no est´ permitida la herencia m´ltiple de clases.12 En el c´digo 4.(b) hace lo propio con la herencia m´ltiple.6.7: Herencia m´ltiple y colisi´n de nombres u o La herencia repetida se da cuando una misma propiedad es heredada por distintos caminos m´s de una vez.6. u Figura 4.10 Se dice que existe herencia m´ltiple de clases (tambi´n puede ser de intero u e faces) cuando una clase hereda directamente de m´s de una clase.5 se muestra un claro ejemplo de o ı herencia m´ltiple de interfaces. Problemas: Colisi´n de nombres y herencia repetida o Aunque la herencia m´ltiple nos ofrece varias ventajas a la hora de programar seg´n la u u metodolog´ OO. u (a) (b) Figura 4.11 La figura 4. u 4. Ejemplo 4. este hecho se solventa mediante la herencia m´ltiple de interfaces u y simple de clases.

como ya hemos dicho. Sobrecarga. u 1 2 3 4 5 6 7 8 9 10 11 12 interface A { void f ( object o ) .. u En C#. si difieren en la signatura y/o en el valor de retorno. } A . si tienen la misma signatura y valor de retorno. tambi´n podemos a e implementar un m´todo f() en C para el caso en el que se manipulen directamente objetos e de dicha clase. o 4. } interface B { void f ( object o ) . Estos cambios pueden observarse en el c´digo 4. Compartici´n. pero s´ puede darse colisi´n de ı o nombres en el caso en el que una interface hereda de dos o m´s interfaces un m´todo con el a e mismo nombre. resultando en una e ambig¨edad de nombres. } B . En este caso existen dos posibilidades: 1.8 se muestra un ejemplo de herencia repetida debida a la herencia m´ltiple. Es m´s. f ( object o ) { . o 1 2 3 4 5 class C : public public public } A.7.. no hay herencia repetida. } } C´digo 4.15 En el c´digo 4. Herencia Figura 4.2.. } class C : A . B void void void { f ( string s ) { . f ( object o ) { .7. Ejemplos de utilidad Ejemplo 4.38 Tema 4. B { // A .7: Soluci´n a la ambig¨edad de nombres o o u .6 se muestra un ejemplo en el que una clase C hereda de dos o interfaces distintas A y B un m´todo con el mismo nombre f(object o).14 En la figura 4.. 2. f () ?? public void g () { f () .6: Ambig¨edad de nombres debida a la herencia m´ltiple o u u Podemos resolver la potencial ambig¨edad de nombres dentro de la clase C incluyendo u declaraciones expl´ ıcitas para cada instancia de interface heredada... } C´digo 4. f () o B .8: Herencia m´ltiple y herencia repetida u Ejemplo 4.

10. Normalmente el recolector de basura (garbage collector ) se encarga autom´ticamente de los objetos que ya no son necesarios (por ejemplo.16 Sea la jerarqu´ mostrada en la figura 4.9. ´ e 4.10: Herencia m´ltiple sin herencia repetida (II) u Si bien es cierto que la clase Z hereda los m´todos de la interface W por dos v´ no resulta e ıas. a Otra soluci´n distinta a la expuesta en el ejemplo 4. Al igual que en el ejemplo ıa anterior. Figura 4. se puede solucionar f´cilmente.8 C#. pues como ya vimos en el ejemplo 4. En esta circunstancia podr´ ıamos pensar que se dar´ un caso de herencia repetida. pero ıa no es as´ ı. C# es muy parecido a Java.15 pero igualmente v´lida consiste en o a implementar una unica vez cada m´todo “repetido”. Java y C++: Estudio comparativo Adem´s de las continuas referencias que durante todo el texto se han hecho hacia otros a lenguajes OO como Java y C++. No obstante s´ deber´ implementar aquellos m´todos de la ı a e interface Y que no est´n en la interface W.8.9: Herencia m´ltiple sin herencia repetida (I) u La clase Z no necesita implementar los m´todos de la interface W. pues ya hereda dichas e implementaciones de la clase X.15. Pero.4. esto ser un problema. clases. a continuaci´n se muestran s´lo algunas comparaciones o o entre dichos lenguajes y C#. C#. los no a . Java y C++: Estudio comparativo 39 Ejemplo 4. e Ejemplo 4. podr´ ıamos pensar que bajo estas premisas nos encontramos ante un caso de herencia m´ltiple.17 Sea ahora la jerarqu´ mostrada en la figura 4. al igual que en el ejemplo anterior esto no es as´ u ı. Figura 4. Las letras enmarcadas representan ıa interfaces y las no enmarcadas.

C++ es muy complejo e inseguro. El mero hecho de que el n´cleo de C# est´ desprovisto del u e tipo puntero simplifica enormemente su compresi´n por parte de un estudiante de POO. C# tiene verdaderos arrays multidimensionales. Toda clase tiene como clase base de su jerarqu´ a ıa la clase object. No es este el caso de Java donde los tipos primitivos son estrictamente “tipos valor”. Herencia referenciados por ninguna variable). o C# ha retenido. En C# todo es un objeto.40 Tema 4. lo cual pero mite la construcci´n de un iterador. En C# existe el concepto de propiedades. aunque de una forma m´s l´gica y simple. o C++ es dependiente del sistema. la habilidad de C++ para a o sobrecargar operadores. pero no a la a o inversa. No maneja la memoria a como lo hacen C# o Java. lo cual proporciona los m´todos de acceso get y set para consultar y modificar los valores de los miembros e de datos de una clase. Los tipos primitivos tales como int pueden ser tratados como objetos. De hecho Java es conceptualmente un subconjunto de C#. C# incorpora la instrucci´n foreach junto con la interface IEnumerator. No est´ preparado para la Web. Un programador de C# puede convertir r´pidamente su c´digo a Java. Ofrece demasiadas oportunidades al programador de manejar err´neamente los punteros en aras de la eficiencia. o . C# permite paso por referencia en los tipos primitivos.

. . . . 2. . . . . . . . . Herencia m´ltiple y colisi´n de nombres . . . Herencia de especializaci´n y de implementaci´n o o 4. . . . . . . . . . .5. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u o 4. . . . . . ıa 4. . . Ejemplo de copia superficial . . Herencia e implementaci´n de interfaces . . . 2. . . . . . . . . . . u 4. . . . . . . . .9. . . . . . . . . .8. . . . . . . . . Ejemplo de estructura de datos polimorfa . . . .2. . . . . . . . . . 2.2. . . . . . . u 4. . . . . . . . . . . . . . . . . . . . . .10. . . .6. . . . . . .´ Indice de Figuras 2. Ejemplo de copia profunda . . . . . . . . . .4. . . .1. . . . . . . . . . . . . . . . . . . . . . 8 11 11 11 12 12 13 25 26 29 30 33 37 37 38 39 39 4. . . . Herencia m´ltiple sin herencia repetida (I) . . . . . . . . . . . . . . . . . . . . . . . 2. . . . . . . . . . . . Herencia m´ltiple sin herencia repetida (II) . e . . . . . . . . . . . . . . . u 41 . . . . . . .7. . . . Jerarqu´ de clases . . . Herencia simple y m´ltiple . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3. . Herencia y redefinici´n de m´todos . . . . . . . . . . . . . . . . . . . . .7. . . . .3. . . u 4. 2. . . . . . .5. Clientela y Herencia entre A y B . . . . . . . o 4. . . . . .6. . 4.4. . . . . . . . . . . . . . . . . . . . Ejemplo de variables id´nticas . . . . Variables en los lenguajes tradicionales . . . . . . o e 4. . 2. . Herencia m´ltiple y herencia repetida . . . . . . . . . . . . . . Variables tipo “puntero” en los lenguajes tradicionales Variables en los lenguajes OO . . . . . . . . . . . . . . .

42 ´ INDICE DE FIGURAS .

. . . . . . . . . . . . . . 2. . . . Operadores unarios “sobrecargables” . . . . . . . . . . . Algunas Excepciones est´ndar . . . . . . . . . . .2. . . . . . . . . . . . . . . . .4. . .1. . . . . . . . . . . . . . .3. . . . . . . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4. . . . . 4. . . . Tipos enteros primitivos .´ Indice de Tablas 2. . . . . . . . . . . . . . Propiedades de las excepciones . Tipos flotantes primitivos Otros tipos primitivos . . . .3. . . . . . . . . .1. 2. . . . .2. . . . . Palabras reservadas . . . Operadores binarios “sobrecargables” . . . . . . . . . . . . . . . . a 3. . . . . . . . . . . . . . . . . . . . Propiedades de las excepciones . . . . . .2. . . . . . . . . . . . 6 6 6 6 19 19 26 27 27 3. . . 2. . . . . . . . . . . . . . . 43 . 4. . . . . . . . . . . . . . . .

44 ´ INDICE DE TABLAS .

. . . . . . .7. . . . . . . . . . . . . . . . . . . . . . . Ejemplo de Sobrecarga de Operadores . . .1. . . . . . . Herencia M´ltiple mediante interfaces . . . . . . . . . .2. . . . .4. . .5. . . . . . . . . . . . . .7. . . . . . . . . 4. . . . . . . . . . . . . o u . o o Otro ejemplo de Ocultaci´n de Informaci´n .1. . . Ejemplo del relanzamiento de excepciones . . . 3. . . . . . . . . . . . 2.5. . o e Lista gen´rica doblemente enlazada . . . . . . . . . . . . 4. . . . . . . . . . . . . 2.´ Indice de C´digos o 2. . . . . . . . . . . . . . . . . 4. . . . 4. . . . . 3. . . . . . . . . .6. . . . . . . . . . . 2. . .4. . . . . o Ambig¨edad de nombres debida a la herencia m´ltiple u u Soluci´n a la ambig¨edad de nombres . e Ejemplo del uso de asertos . . . . . . . . . . . . . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2. . . . . . . . 3. . . . . . o o Ejemplo de Clases Anidadas . . . . . . . . . . . . . Ejemplo de implementaci´n del m´todo Clone() . . . 2. .2. . . .2. . 4. . . . . . . . . Ejemplo del uso de excepciones . Redifinici´n de un m´todo heredado . . . . . . . .3. . u Implementaci´n de un iterador . . . . . . . . . . . . . . . Clase Luna . . . . . . . . . .3. . . . . . . . Ejemplo de Ocultaci´n de Informaci´n . 3. . . .5. . 2. . . . . . . . . . . . . . . . . . . . . . . o e Clase abstracta Figura . . . . . . . . . . . . . . .1. . . 3. . . .4. . . . . . . . . . . . . . . . . . .6. . . . . 4. . . . . . . Uso de excepciones con m´s informaci´n . . . . . . . 5 7 8 9 12 13 14 18 18 20 21 22 28 31 31 33 35 38 38 45 . . . . . . . . . . a o Ejemplo del uso de excepciones en vez de asertos . . . . . . . . . . . . . . . . 4. . . . . . . . . Ejemplo de Constructores . . . . . . . . . . . . . . . . . . . . . . .

46 ´ ´ INDICE DE CODIGOS .

Lippman. 2003. 2002. C# Primer. [Mol04] J. C# by Dissection. University of California.Bibliograf´ ıa [Lip02] Stanley B. 47 . Addison Wesley. 2004. A Practical Approach. ıa o [Poh03] Ira Pohl. Garc´ Molina. Apuntes de programaci´n orientada a objetos. Addison Wesley.

Sign up to vote on this title
UsefulNot useful