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

lunaKilo = ( int ) ( luna * 1.1.609) . public class Luna { public static void Main () { int luna = 238857. Estructura Los componentes principales de una clase. y M´todos. convierte a kil´metros la o o distancia de la Tierra a la Luna en millas. WriteLine (" De la Tierra a la Luna = " + luna + " millas ") . Console . 2. llamada Luna.1. son: Atributos. 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.") .1: Clase Luna o 5 .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 . que determinan una estructura de almacenamiento para cada objeto de la clase.Tema 2 Clases y Objetos 2. WriteLine (" Kil´ metros = " o + lunaKilo + " km . que a partir de ahora llamaremos miembros.1 La clase mostrada en el c´digo 2. int lunaKilo .1. Clases Definici´n 2. que no son m´s que operaciones aplicables sobre los objetos. } } C´digo 2.1 Una clase es una implementaci´n total o parcial de un tipo abstracto de o o dato (TAD). Console . e a Ejemplo 2.

1. 7. false} Tabla ASCII Tabla 2. Alberto = 15}).2 y 2.1: Tipos enteros primitivos Tipo float double decimal Bytes 4 8 16 Rango de Valores (±3. 32767) (0. 18446744073709551615) Tabla 2. Para declarar un tipo consistente en un conjunto etiquetado de constantes enteras se emplea la palabra clave enum (por ejemplo.3 muestran los tipos primitivos soportados por C#. Alex.7 × 1038 ) de 15 a 16 d´ ıgitos significativos −28 . e Palabras reservadas La tabla 2.2: Tipos flotantes primitivos Tipo byte ubyte bool char Bytes 1 1 1 2 Rango de Valores (-128. enum Edades {F´lix = 21. 2. Clases y Objetos Tipo short ushort int uint long ulong Bytes 2 2 4 4 8 8 Rango de Valores (-32768. 9223372036854775807) (0.9 × 10+28 ) de 28 a 29 d´ (10 ıgitos significativos Tabla 2.4 muestra las palabras reservadas de C#. 65535) (-2147483648.6 Tema 2.3: Otros tipos primitivos Tipos de datos primitivos Las tablas 2.255) {true. 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. 4294967295) (-9223372036854775808. 2147483647) (0.4 × 1038 ) 7 d´ ıgitos significativos (±1.4: Palabras reservadas .127) (0.

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

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

4 muestra un ejemplo de clases anidadas.4: Ejemplo de Clases Anidadas o .4.2. se puede modificar la implementaci´n de e o B sin que esto afecte a A). } public class Dos { public int c . 2. return u .c = 5 + e. y = new Tres () .1.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.c = c = e.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. } public class PruebaAnidada { public static void Main () { Dos x = new Dos () . } public Tres y . WriteLine (" IntAnidado (6) = " + IntAnidado (6) ) . sin afectar a ´ste (en nuestro ejemplo. u. } private int c . public class Tres { public int IntAnidado ( int e ) { Dos d = new Dos () . Console . pues en ´sta ultima se puede cambiar la implementaci´n de la clase que se emplea e ´ o en el cliente. d.1. x . 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 . } } C´digo 2. c + c .6 El c´digo 2. o o Definici´n 2. en a o o esta secci´n trataremos la cuesti´n de las clases anidadas.2 acerca de la ocultaci´n de informaci´n. Uno u = new Uno () . Visibilidad Adem´s de lo comentado en el apartado 2. Ejemplo 2.

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

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

pues ıa con el recolector de basura es suficiente para la finalizaci´n.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. public public public { get set } public } C´digo 2. Clases y Objetos Ejemplo 2. } // Constructor por defecto Contador ( int i ) { conta = i % 100. Destructores Un destructor es un m´todo cuyo nombre es el nombre de la clase precedido de una tilde e ∼.5. Figura 2.5). 1 2 3 4 5 6 7 8 9 10 11 12 public class Contador { private int conta . en la mayor´ de los casos las clases no necesitan destructores. Sem´ntica de la asignaci´n e igualdad entre objetos a o Definici´n 2.5: Ejemplo de Constructores o Contador () { conta = 0. e o Figura 2.6). o 2. Mientras que los constructores s´ pueden tener modificadores de acceso.5 muestra un ejemplo de una clase con un constructor y un conso tructor por defecto. } void Click () { conta = ( conta + 1) % 100.6: Ejemplo de copia profunda 3 garbage collector .5: Ejemplo de copia superficial Definici´n 2. los destructores ı carecen de ellos. No obstante. } // Constructor int Conta { return conta . } { conta = value % 100.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.8 El c´digo 2.6.1.12 Tema 2. Cuando un objeto es recogido por el recolector de basura3 se llama impl´ ıcitamente a su destructor. } 2.

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

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

while ( h != null ) { if ( val . Data . Previous . } else { DListElement h = new DListElement ( val . Equals ( h . head ) . } } public object Front () { if ( IsEmpty () ) throw new System . return h . return head . Exception (" Empty DList ") . Previous = h . Previous = pp . else head = null .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 . h = h . } return h . } public void Add ( object val ) { if ( IsEmpty () ) { head = new DListElement ( val ) . DListElement np = h . Next = head . } public DListElement Find ( object val ) { DListElement h = head . head = h . Data ) ) break .2. } . Previous = null . Next . head . Next = np . Next . Next . } private DListElement Delete ( DListElement h ) { if ( h == null ) return null . if ( np != null ) np . head . pp = h . if ( pp != null ) pp .

y en la l´ ınea 90 vemos c´mo se sobrescribe el m´todo heredado ToString()4 . 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 ) ) . El empleo del operador e == en esta l´ ınea provocar´ una ejecuci´n incorrecta. En la l´ ınea 65 vemos un ejemplo de uso del m´todo Equals. Como se observa en la l´ ınea 23 de este c´digo los datos almacenados en la lista son de o tipo object. as´ como la sobrecarga de constructores en las l´ ı ıneas 4 y 6. Data + "\ n ") + ToStr ingRec ursive ( first . las cuales trataremos en el siguiente tema. distinta a la esperada. } static string To String Recursive ( DListElement first ) { if ( first == null ) return "". o e 4 Todo lo relacionado con la herencia se ver´ en profundidad en el tema 4 a . ıa o En la l´ ınea 55 se ve un ejemplo del uso de excepciones. as´ es como se consigue “genericidad” en ı C#. } private DListElement head .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. Como ya se dijo anteriormente. Next ) . Es este un ejemplo de ocultaci´n de o informaci´n. } C´digo 2. } public override string ToString () { return ToStr ingRec ursive ( head ) . 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. Podemos ver la implementaci´n de un constructor por defecto y un constructor en las o l´ ıneas 28 y 29. respectivamente.16 Tema 2. else return ( first . respectivamente.

mensaje). el software realizar´ la tarea deseada satisfactoriamente. la ejecuci´n proporciona una o o u o salida de diagn´stico. 3. Los asertos se habilitan definiendo la variable o DEBUG. o Si la expresi´n expresi´n booleana se eval´a como falsa. por su parte.Tema 3 Dise˜ o por Contrato: Asertos y n Excepciones En este tema se describe el manejo de excepciones en C#. El proveedor (servidor). o 17 . invocado de la siguiente manera: e Assert(expresi´n booleana. con el mensaje mensaje. as´ como del empleo o ı de listeners para visualizar los mensajes de diagn´stico por pantalla. 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. Las excepciones son habitualmente condiciones inesperadas de error que provocan la finalizaci´n del programa en el que o tienen lugar. que se cumplen las postcondiciones. no se lleva a cabo en la mayor´ de las ocasiones. siempre que la entrada sea correcta. C#. De hecho.2.1 se muestra un ejemplo del uso de asertos. con un mensaje de error. o pero por desgracia. 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. o Ejemplo 3. a Establecer una prueba formal completa de correcci´n del software es algo muy deseable. el usuario (cliente) debe garantizar que se cumplen las condiciones u necesarias para una correcta aplicaci´n del software. Para acceder a dicha salida de diagn´stico se emplean los listener.1 En el c´digo 3. ı o 3. Si esto es as´ se dice a ı. A estas condiciones se le conocen como o precondiciones. si el cliente cumple con las precondiciones. sin embargo permite al programador intentar recuperarse frente a estas situaciones y as´ continuar con la ejecuci´n del programa. 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. debe garantizar que. Seg´n este modelo.1. o ıan En C# la clase Debug contiene el m´todo Assert().

double x . Add ( new T e x t W r i t e rT r ac eL i st e ne r ( Console . using System . readLine () . con un bloque try.2 El c´digo 3. Listeners . o la expresi´n throw y los manejadores definidos mediante la palabra clave catch. 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 . o 1 2 3 4 5 6 7 8 using System . public class AssertSqrRoot { public static void Main () { Debug . public class LanzaExcepcion { public static void Main () { try { double x . Console . WriteLine ( x ) . Console . 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. 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. ı } } C´digo 3. " Valor no positivo ") . Listeners . x = double . Clear () .Exception.3. o El mecanismo de manejo de excepciones en C# es sensible al contexto. Ejemplo 3. Assert ( x > 0 . string datos . Un c´digo de C# puede alcanzar una excepci´n en un bloque try mediante la expresi´n o o o throw. Out ) ) . Excepciones en C# C# contiene la clase est´ndar System. Console . . La excepci´n es entonces tratada por alguno de los manejadores que se encuentran al o final del bloque try. Y dicho contexto no es m´s que un bloque try.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.2 muestra un ejemplo del uso de excepciones. o o 3. Parse ( datos ) .18 Tema 3. Diagnostics . string datos . en el cual se declaran los manejadores (handlers) al final del a mismo mediante la palabra clave catch. u datos = Console . Sqrt ( x ) ) . Debug . WriteLine (" Introduzca un n´ mero real positivo :") . WriteLine (" La ra´ z cuadrada es " + Math . Debug .

3 Excepciones en C# 19 9 10 11 12 13 14 15 16 17 18 19 20 21 Console . 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. WriteLine ( x ) .3.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. if ( x > 0) throw ( new System . mientras que en la tabla 3. datos = Console . readLine () .2: Propiedades de las excepciones . else Console . } o } } C´digo 3.2 a podemos observar las propiedades est´ndar que toda excepci´n debe tener. Parse ( datos ) . Exception () ) .1 muestra algunas excepciones est´ndar en C#. Sqrt ( x ) ) .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. } catch ( Exception e ) { Console . WriteLine (" La ra´ z cuadrada es " ı + Math . WriteLine (" Lanzada excepci´ n " + e ) . WriteLine (" Introduzca un double :") .2: Ejemplo del uso de excepciones o La tabla 3. x = double .

las cuales deben ser objetos de la o clase Exception.20 Tema 3. Sin embargo. 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. . o Ejemplo 3. throw new Exception (" Lanzada en LanzaMsg ") . . . . throw . public class ReLanzaExcepcion { public static void LanzaMsg () { try { . 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.3: Ejemplo del relanzamiento de excepciones o Conceptualmente. el lanzamiento de una excepci´n pasa cierta informaci´n a los manejao o dores. // Relanzamiento } } public static void Main () { try { . Lanzamiento de excepciones Mediante la expresi´n throw se lanzan excepciones. 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. WriteLine (" Excepci´ n recapturada " + e ) . pero con frecuencia ´stos no precisa de dicha informaci´n. 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. } catch ( Exception e ) { . . . . .3 El c´digo 3. 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 .3 muestra un ejemplo del relanzamiento de excepciones. 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. } o } } C´digo 3. En este caso ser´ o ıa apropiado “empaquetar” la informaci´n en un objeto derivado de una clase Exception ya o existente. . Por ejemplo. .1. Console . LanzaMsg () . . } catch ( Exception e ) { Console . WriteLine (" Primera captura " + e ) .3. Dise˜ o por Contrato: Asertos y Excepciones n 3. . .

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

mientras que con las excepciones. el cual maneja las excepciones no u tratadas por los manejadores que s´ tienen argumento.3.5 es una reescritura del c´digo 3. 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. public class ExAssert { public static void MyAssert ( bool cond . Console .1 que se muestra en el ejemplo o o 3. string message . 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. adem´s de imprimir m´s informaci´n. o Ejemplo 3. 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. Error . 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.22 Tema 3. e o 3. WriteLine ( message ) .5 Seg´n el siguiente c´digo: u o catch(ErrorClaseBase e) catch(ErrorClaseDerivada e) nunca se ejecutar´ el cuerpo del segundo catch. WriteLine (" Introduzca un double positivo :") . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 using System . o Los asertos simplemente imprimen un mensaje por pantalla.4. } } } class ExceptionSqrRoot { public static void ConsoleSqrt () { double x . seg´n lo dicho en las condiciones anteriores. . string datos . Exception e ) { if (! cond ) { Console . throw e . u 3. Dise˜ o por Contrato: Asertos y Excepciones n Ejemplo 3. como ya hemos visto anteriormente. pues antes se encontrar´ una coincidencia ıa ıa con el primer catch. 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. ı Cuando se invoca a un manejador a trav´s de una expresi´n throw.3. pero ahora mediante excepciones.6 El c´digo 3. Manejadores La sentencia catch parece la declaraci´n de un m´todo con un solo argumento y sin valor o e de retorno.1 del uso de asertos.

ToString () .5: Ejemplo del uso de excepciones en vez de asertos o . Sqrt ( x ı )). // Se vuelve a intentar } } public static void Main () { Console . Console . WriteLine ( e ) . } } C´digo 3. WriteLine (" Probando Ra´ ces Cuadradas ") . ConsoleSqrt () . } catch ( Exception e ) { Console . ExceptionSqrRoot . try { ExAssert . " Valor no positivo : x = " + x .3. WriteLine (" La ra´ z cuadrada es " + Math . Console . x = double . ı ConsoleSqrt () . readLine () . MyAssert ( x > 0 . new Exception () ) .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 . WriteLine ( x ) . Parse ( datos ) .

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

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

ıa bool Equals(object o) void Finalize() int GetHashCode() Type GetType() object MemberwiseClone() bool ReferenceEquals (object a.1: Propiedades de las excepciones 4.3. los ejemplos de las figuras 4. o Por otra parte. object b) string ToString() Devuelve true si dos objetos son equivalentes. 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. m´s refinada) de A.2. as´ como en las figuras ı 4. ra´ en toda e u ız jerarqu´ de clases de C#. puede ocurrir que el motivo por el cual B hereda de A sea la necesidad de construir una implementaci´n “distinta” (si se quiere. o a Ejemplo 4.2. una clase B puede heredar de otra clase A. por ser B una especializaci´n de A. o o Esto es. Sin o embargo.2. o Figura 4. la herencia es. a la vez. un mecanismo de especialio zaci´n y un mecanismo de implementaci´n.1. Herencia La tabla 4. 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. o Podr´ ıamos categorizar el polimorfismo en dos tipos: Param´trico e Real y Aparente → Sobrecarga Inclusi´n (basado en la herencia) o .a y 4. si no.b sirve como mecanismo de especializaci´n. Doble aspecto de la herencia Como ya se dijo en la definici´n 2.1 muestra los m´todos p´blicos y protegidos de la clase object.2.d muestran la herencia como mecanismo de implementaci´n. Polimorfismo Definici´n 4.2 La herencia entre clases que se observa en la figura 4.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.c y 4.26 Tema 4.2.3. o C# soporta el polimorfismo.2: Herencia de especializaci´n y de implementaci´n o o 4.

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

tanto unarios. hours = ( i / 3600) % 24. totSecs + c2 . 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 . days . } public static MyClock operator *( uint m . hours . } public void Reset ( unit i ) { totSecs = i . Obs´rvese como en la l´ e ınea 32 se vuelve a definir el operador ‘*’.1 muestra un ejemplo de sobrecarga de operadores. MyClock c ) { return new MyClock ( m * c . hours = 0 . Herencia Ejemplo 4. Tick () . return String .5 El c´digo 4. class MyClock { public MyClock () { } public MyClock ( unit i ) { Reset ( i ) . mins = ( i / 60) % 60. } public override string ToString () { Reset ( totSecs ) . days = 0. 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 c ) { c . days = i / 86400. mins . } public static MyClock operator *( MyClock c . mins = 0 . uint m ) { return ( m * c ) . secs ) . pero con los par´metros en orden inverso. } . o como binarios. secs = 0 . MyClock c2 ) { return new MyClock ( c1 . } public void Tick () { Reset (++ totSecs ) . return c . totSecs ) . totSecs ) . previamente sobrecargado por el m´todo de la l´ e ınea 29.28 Tema 4. Format (" day {0: D2 } time :{1: D2 }:{2: D2 }:{3: D2 }" . secs = i % 60. } public static MyClock operator +( MyClock c1 . } private uint totSecs = 0 .

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

f → α oa = od. C oc = new C(). como en C++. 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. la versi´n del m´todo que se ejecute depender´ del tipo din´mico del o e a a objeto de la clase A. oa. 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. 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. 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. 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.6 En la figura 4. como ya hemos visto en varios a ejemplos con el m´todo ToString(). B ob = new B(). la ligadura es est´tica por defecto. D od = new D().1. Las letras griegas representan la versi´n de cada e o m´todo. e Figura 4. B puede o redefinir m´todos de A e implementar m´todos que en A sean diferidos.f → β oa = oc. a saber. 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.7 El c´digo 4. Ligadura Din´mica a Como ya dijimos en la definici´n 4. si una clase B hereda de otra clase A. Obs´rvese el uso de la palabra clave virtual en la l´ e ınea 4. din´mico del objeto oa: a oa = ob. Herencia 4.30 Tema 4. e N´tese la diferencia entre un m´todo redefinido y un m´todo sobrecargado. En esto consiste la ligadura din´mica.4.2 muestra un ejemplo de redefinici´n de un m´todo heredado de la o o e clase base. void. oa. Un m´todo redefinido. e Ejemplo 4. A continuaci´n se muestra qu´ versi´n del m´todo f se ejecutar´ dependiendo del tipo o e o e ıa.4: Herencia y redefinici´n de m´todos o e Dadas las siguientes declaraciones: A oa. por contra. as´ como de la palabra clave ı override en la l´ ınea 9.4 se muestra una jerarqu´ de clases en las que algunas de ellas ıa redefinen el m´todo f de sus ancestras.f → δ En C#. oa. 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 . a Ejemplo 4.

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

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

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

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

la segunda la 1. o En C# existe una gran colecci´n (a´n en crecimiento) de elementos reutilizables. as´ como el m´todo de acceso Current. Collections . o El resultado mostrado por pantalla ser´ ıa: 1 3 5 7 9 11 13 15 17 19 Iterando. class ArrayImpar : IEnumerable { public int [] a = new int [10]. } set { a [ i ] = value .6 Herencia. } public int this [ int i ] { get { return a [ i ]. Captura de similitudes entre un un subgrupo de un conjunto de posibles implementaciones. la creaci´n o o o de componentes reutilizables. para realizar una implementaci´n concreta deben implementarse (valga la reo dundancia) los m´todos MoveNext() y Reset(). Obs´rvese que este valor no puede ser modificado. todos e ı e ellos de la interface IEnumerator. s´lo e o puede consultarse. la utilizaci´n de dichos componentes.). using System . 3 7 11 15 19 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 using System . o o Existen dos aspectos importantes en la reutilizaci´n de c´digo: por una parte. Noo u sotros trataremos ahora brevemente el contenido de System. . 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.IEnumerable. Conseguida mediante la construcci´n de clases.4.. public IEnumerator GetEnumerator () { return ( IEnumerator ) new ArrayImparEnumerator ( this ) . 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.. 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. e No obstante. Ejemplo 4. Conseguida gracias a la herencia.10 El c´digo 4. Agrupaci´n de rutinas relacionadas.5 muestra un ejemplo de una clase que implementa la interface o IEnumerable. } } 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 ) .. 5.Collections y la interface Collections. de modo que se podr´ emplear la instrucci´n foreach con objetos de dicha a o clase (como puede observarse en la l´ ınea ). reutilizaci´n y extensibilidad del software o 35 4. o Para ello la interface IEnumerable declara el m´todo IEnumerator GetEnumerator(). Para construir un iterador necesitamos alguna manera de avanzar el iterador. 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.. y por otra parte.

llamadas selladas. foreach ( int elemento in ai ) Console .1. Console .2 existe otro m´s: internal.") . } public void Reset () { indice = -1. no es soportada en C#. 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. Write ( ai . a s´ se puede inhabilitar la herencia de una clase mediante la palabra clave sealed. 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. i < 10. } } C´digo 4. } Console . ya que sus m´todos no pueden ser redefinidos y por tanto se declaran autom´ticamente e a como no virtuales. que est´ permitida en C++. e a o Adem´s de los tres tipos de acceso vistos en la secci´n 2. pues puede ocurrir que una subclase apoye algunos de sus m´todos en la implementaci´n concreta e o conocida de la clase base. 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 . a [ i ] = 2 * i + 1. return ( indice <= 9) . La herencia privada. pues si modificamos la clase base. a = a . ´ Este es un factor negativo para la extensibilidad. } } private int indice . Sin embargo. } public bool MoveNext () { indice += 2.. } class ArrayImparTest { public static void Main () { ArrayImpar ai = new ArrayImpar () .36 Tema 4. for ( int i = 0. } publoc object Current { get { return a [ indice ]. WriteLine ("\ nIterando . Write ( elemento + " ") . .. indice = -1. i ++) { ai . Este tipo de ı clases.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. a [ i ] + " ") . private ArrayImpar a . pueden ser tratadas de una forma m´s eficiente por parte del compia lador.

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.(a) muestra un ejemplo de herencia simple.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. este hecho se solventa mediante la herencia m´ltiple de interfaces u y simple de clases. mientras que la figura 4.4.7. 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.6. a diferencia de C++. no se da en C#). al igual que en Java. ıa e A continuaci´n explicaremos dos de ellos: la colisi´n de nombres y la herencia repetida o o (aunque ´sta ultima. Ejemplo 4.7. Herencia m´ ltiple u Definici´n 4.6: Herencia simple y m´ltiple u En C#.6.5 se muestra un claro ejemplo de o ı herencia m´ltiple de interfaces. tambi´n implica algunos inconvenientes. como veremos m´s adelante.7 se muestra un ejemplo de colisi´n de nombres debida a la o herencia m´ltiple. no est´ permitida la herencia m´ltiple de clases.(b) hace lo propio con la herencia m´ltiple.11 La figura 4. a Ejemplo 4. e o Ejemplo 4.13 En la figura 4.1.4 as´ como en la figura 4. Sin ema u bargo. a .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.7 Herencia m´ ltiple u 37 4.12 En el c´digo 4. u 4. u Figura 4. u (a) (b) Figura 4.

f () o B .7.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).8 se muestra un ejemplo de herencia repetida debida a la herencia m´ltiple. f ( object o ) { . Es m´s. Ejemplos de utilidad Ejemplo 4.. Estos cambios pueden observarse en el c´digo 4. } B . Herencia Figura 4.2. } A . 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. B { // A . } C´digo 4.8: Herencia m´ltiple y herencia repetida u Ejemplo 4.. En este caso existen dos posibilidades: 1. f ( object o ) { .. o 4. si tienen la misma signatura y valor de retorno. u En C#. Sobrecarga. o 1 2 3 4 5 class C : public public public } A... 2. Compartici´n. B void void void { f ( string s ) { . resultando en una e ambig¨edad de nombres. } interface B { void f ( object o ) .7. u 1 2 3 4 5 6 7 8 9 10 11 12 interface A { void f ( object o ) .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.38 Tema 4.7: Soluci´n a la ambig¨edad de nombres o o u .15 En el c´digo 4. 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. si difieren en la signatura y/o en el valor de retorno. no hay herencia repetida. } class C : A ..14 En la figura 4. f () ?? public void g () { f () . como ya hemos dicho. } } C´digo 4.

pues ya hereda dichas e implementaciones de la clase X. podr´ ıamos pensar que bajo estas premisas nos encontramos ante un caso de herencia m´ltiple. se puede solucionar f´cilmente. 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++.9: Herencia m´ltiple sin herencia repetida (I) u La clase Z no necesita implementar los m´todos de la interface W. ´ e 4. al igual que en el ejemplo anterior esto no es as´ u ı. a Otra soluci´n distinta a la expuesta en el ejemplo 4.16 Sea la jerarqu´ mostrada en la figura 4. C# es muy parecido a Java.15.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. No obstante s´ deber´ implementar aquellos m´todos de la ı a e interface Y que no est´n en la interface W.9.10. pero ıa no es as´ ı. Figura 4. Java y C++: Estudio comparativo 39 Ejemplo 4.4. clases. Pero. esto ser un problema. Normalmente el recolector de basura (garbage collector ) se encarga autom´ticamente de los objetos que ya no son necesarios (por ejemplo. a continuaci´n se muestran s´lo algunas comparaciones o o entre dichos lenguajes y C#. Al igual que en el ejemplo ıa anterior.15 pero igualmente v´lida consiste en o a implementar una unica vez cada m´todo “repetido”. e Ejemplo 4. Las letras enmarcadas representan ıa interfaces y las no enmarcadas. pues como ya vimos en el ejemplo 4.17 Sea ahora la jerarqu´ mostrada en la figura 4.8. Figura 4. C#.8 C#. En esta circunstancia podr´ ıamos pensar que se dar´ un caso de herencia repetida. los no a .

la habilidad de C++ para a o sobrecargar operadores. Toda clase tiene como clase base de su jerarqu´ a ıa la clase object. Un programador de C# puede convertir r´pidamente su c´digo a Java. En C# existe el concepto de propiedades. Herencia referenciados por ninguna variable). 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. aunque de una forma m´s l´gica y simple. No est´ preparado para la Web. No maneja la memoria a como lo hacen C# o Java. pero no a la a o inversa. o C# ha retenido. Ofrece demasiadas oportunidades al programador de manejar err´neamente los punteros en aras de la eficiencia. De hecho Java es conceptualmente un subconjunto de C#. C++ es muy complejo e inseguro. Los tipos primitivos tales como int pueden ser tratados como objetos. o . C# permite paso por referencia en los tipos primitivos. C# incorpora la instrucci´n foreach junto con la interface IEnumerator. 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. No es este el caso de Java donde los tipos primitivos son estrictamente “tipos valor”.40 Tema 4. o C++ es dependiente del sistema. lo cual pero mite la construcci´n de un iterador. En C# todo es un objeto.

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

42 ´ INDICE DE FIGURAS .

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

44 ´ INDICE DE TABLAS .

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

46 ´ ´ INDICE DE CODIGOS .

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

Sign up to vote on this title
UsefulNot useful