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

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

3: Otros tipos primitivos Tipos de datos primitivos Las tablas 2. Alberto = 15}). 65535) (-2147483648.255) {true. 2.6 Tema 2. 32767) (0.7 × 1038 ) de 15 a 16 d´ ıgitos significativos −28 .4 × 1038 ) 7 d´ ıgitos significativos (±1. Alex.1. 9223372036854775807) (0. 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.127) (0. 2147483647) (0.4 muestra las palabras reservadas de C#. e Palabras reservadas La 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#.9 × 10+28 ) de 28 a 29 d´ (10 ıgitos significativos Tabla 2. Clases y Objetos Tipo short ushort int uint long ulong Bytes 2 2 4 4 8 8 Rango de Valores (-32768. 7.1: Tipos enteros primitivos Tipo float double decimal Bytes 4 8 16 Rango de Valores (±3.2 y 2. 18446744073709551615) Tabla 2. enum Edades {F´lix = 21.2: Tipos flotantes primitivos Tipo byte ubyte bool char Bytes 1 1 1 2 Rango de Valores (-128.4: Palabras reservadas . 4294967295) (-9223372036854775808. false} Tabla ASCII Tabla 2.

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

3.3: Otro ejemplo de Ocultaci´n de Informaci´n o o o 2. Definici´n 2. } // Acceso de lectura set { // Acceso de escritura if ( value . en cambio. .1. mientras que en la 2.b se o observa la relaci´n de herencia entre dichas clases. as´ como que pueda ser usada por el mayor n´mero de clientes ı u posible. conocer su especificaci´n. o e El creador de la clase. Length != 0 ) m_file_output = value . Relaciones entre clases: Cliente-Servidor y Herencia Un cliente de una clase debe ver a ´sta como un TAD. variable local) e es de o a tipo B. } .2 Una clase A se dice que es cliente de una clase B. } Por su parte. .b: class A: B { . el siguiente c´digo muestra la relaci´n de herencia mostrada en la figura o o 2.8 Tema 2. . adaptable. o A⇐B (a) B ↑ A (b) Figura 2. // 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. o bien si A es una implementaci´n de B (herencia o o de implementaci´n). } } } C´digo 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 .1: Clientela y Herencia entre A y B Ejemplo 2.5 El siguiente c´digo muestra la relaci´n de clientela vista en la figura 2. si A es una versi´n especiao o lizada de B (herencia de especializaci´n).1. si A contiene una declao raci´n en la que se establezca que cierta entidad (atributo.a muestra la relaci´n de clientela entre A y B. . B conta.3 Una clase A se dice que hereda de otra clase B.1. y eficiente. Definici´n 2. e o pero sin importarle su implementaci´n (siempre que ´sta sea eficiente y potente). . o La figura 2.1. par´metro. es decir.a: o o class A { . .1.

o o Definici´n 2. u.6 El c´digo 2.2 acerca de la ocultaci´n de informaci´n. Uno u = new Uno () . en a o o esta secci´n trataremos la cuesti´n de las clases anidadas. } public class Dos { public int c . Visibilidad Adem´s de lo comentado en el apartado 2. c + c .4. Ejemplo 2. return u . WriteLine (" IntAnidado (6) = " + IntAnidado (6) ) .1.c = c = e.4: Ejemplo de Clases Anidadas o . } } C´digo 2. 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 . sin afectar a ´ste (en nuestro ejemplo. } public class PruebaAnidada { public static void Main () { Dos x = new Dos () . 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.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. 2. se puede modificar la implementaci´n de e o B sin que esto afecte a A).4 muestra un ejemplo de clases anidadas.2. } public Tres y . x .c = 5 + e. y = new Tres () .1. } private int c .1 Clases 9 Por ultimo cabe decir que la herencia es una decisi´n de dise˜o m´s comprometedora que ´ o n a la clientela. d.

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

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

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

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

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

Previous = null . } private DListElement Delete ( DListElement h ) { if ( h == null ) return null . } . Previous = pp . } public void Add ( object val ) { if ( IsEmpty () ) { head = new DListElement ( val ) . } return h . return h . head ) .2. Next .8 Definici´n de una clase “Lista Doblemente Enlazada” o 15 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 public bool IsEmpty () { return head == null . } public DListElement Find ( object val ) { DListElement h = head . head . Previous . DListElement np = h . if ( np != null ) np . head = h . Previous = h . Next = np . } } public object Front () { if ( IsEmpty () ) throw new System . return head . Data . while ( h != null ) { if ( val . Next . Exception (" Empty DList ") . Next . else head = null . Next = head . head . Data ) ) break . Equals ( h . if ( pp != null ) pp . } else { DListElement h = new DListElement ( val . h = h . pp = h .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

i < 10. pues si modificamos la clase base.36 Tema 4. ya que sus m´todos no pueden ser redefinidos y por tanto se declaran autom´ticamente e a como no virtuales. for ( int i = 0. Write ( ai .2 existe otro m´s: internal. } publoc object Current { get { return a [ indice ]. a [ i ] + " ") . La herencia privada. indice = -1.") . a = a . pues puede ocurrir que una subclase apoye algunos de sus m´todos en la implementaci´n concreta e o conocida de la clase base. 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. WriteLine ("\ nIterando . } public bool MoveNext () { indice += 2. Console . . Este tipo de ı clases. pueden ser tratadas de una forma m´s eficiente por parte del compia lador.. a s´ se puede inhabilitar la herencia de una clase mediante la palabra clave sealed.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. foreach ( int elemento in ai ) Console . 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. que est´ permitida en C++. a [ i ] = 2 * i + 1. e a o Adem´s de los tres tipos de acceso vistos en la secci´n 2. Write ( elemento + " ") . } class ArrayImparTest { public static void Main () { ArrayImpar ai = new ArrayImpar () . return ( indice <= 9) . private ArrayImpar a .. } public void Reset () { indice = -1. i ++) { ai . llamadas selladas.1. no es soportada en C#. } } C´digo 4. ´ Este es un factor negativo para la extensibilidad. Sin embargo. } Console . } } private int indice . 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 diferencia de C++.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. 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.12 En el c´digo 4.7 se muestra un ejemplo de colisi´n de nombres debida a la o herencia m´ltiple. u (a) (b) Figura 4. u Figura 4. u 4.7.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. mientras que la figura 4.5 se muestra un claro ejemplo de o ı herencia m´ltiple de interfaces.1. como veremos m´s adelante. 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. este hecho se solventa mediante la herencia m´ltiple de interfaces u y simple de clases.7 Herencia m´ ltiple u 37 4. a . a Ejemplo 4. Herencia m´ ltiple u Definici´n 4. e o Ejemplo 4. ıa e A continuaci´n explicaremos dos de ellos: la colisi´n de nombres y la herencia repetida o o (aunque ´sta ultima.(a) muestra un ejemplo de herencia simple.11 La figura 4. tambi´n implica algunos inconvenientes.4 as´ como en la figura 4. Sin ema u bargo. al igual que en Java.(b) hace lo propio con la herencia m´ltiple.6.4.6: Herencia simple y m´ltiple u En C#.7.13 En la figura 4. Ejemplo 4. no est´ permitida la herencia m´ltiple de clases.6. no se da en C#).

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

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

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

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

42 ´ INDICE DE FIGURAS .

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

44 ´ INDICE DE TABLAS .

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

46 ´ ´ INDICE DE CODIGOS .

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

Sign up to vote on this title
UsefulNot useful