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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

42 ´ INDICE DE FIGURAS .

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

44 ´ INDICE DE TABLAS .

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

46 ´ ´ INDICE DE CODIGOS .

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

Sign up to vote on this title
UsefulNot useful