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

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

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

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

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

d.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. Console . } public Tres y .4: Ejemplo de Clases Anidadas o . se puede modificar la implementaci´n de e o B sin que esto afecte a A). Visibilidad Adem´s de lo comentado en el apartado 2. u. c + c . sin afectar a ´ste (en nuestro ejemplo. Ejemplo 2. } public class Dos { public int c . y = new Tres () . WriteLine (" IntAnidado (6) = " + IntAnidado (6) ) . o o Definici´n 2.4 muestra un ejemplo de clases anidadas. public class Tres { public int IntAnidado ( int e ) { Dos d = new Dos () . } public class PruebaAnidada { public static void Main () { Dos x = new Dos () . pues en ´sta ultima se puede cambiar la implementaci´n de la clase que se emplea e ´ o en el cliente.1. } } C´digo 2.1. o El resultado mostrado por pantalla ser´ ıa: IntAnidado(6) = 17 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class Uno { public int c .c = c = e.1 Clases 9 Por ultimo cabe decir que la herencia es una decisi´n de dise˜o m´s comprometedora que ´ o n a la clientela.2 acerca de la ocultaci´n de informaci´n. x .4. } private int c .6 El c´digo 2. 2. en a o o esta secci´n trataremos la cuesti´n de las clases anidadas. Uno u = new Uno () .c = 5 + e. return u .2.

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

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

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

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

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

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

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

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

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

Sqrt ( x ) ) . datos = Console . a o SystemException ApplicationException ArgumentException ArgumentNullException ArgumentOutOfRangeException ArithmeticException DivideByZeroException IndexOutOfRangeException InvalidCastException IOException NullReferenceException OutOfMemoryException Clase base para las excepciones del sistema Clase base para que los usuarios proporcionen errores de aplicaci´n o Uno o m´s argumentos son inv´lidos a a Pasado null no permitido Fuera de los valores permitidos Valor infinito o no representable Auto-explicativa ´ Indice fuera de los l´ ımites del array Cast no permitido Clase base en el espacio de nombres System. Console .1 muestra algunas excepciones est´ndar en C#. WriteLine (" Introduzca un double :") . Exception () ) .3. } o } } C´digo 3. readLine () . else Console . WriteLine (" Lanzada excepci´ n " + e ) .3 Excepciones en C# 19 9 10 11 12 13 14 15 16 17 18 19 20 21 Console . Parse ( datos ) .2: Propiedades de las excepciones .2: Ejemplo del uso de excepciones o La tabla 3.2 a podemos observar las propiedades est´ndar que toda excepci´n debe tener. mientras que en la tabla 3. WriteLine ( x ) . } catch ( Exception e ) { Console . WriteLine (" La ra´ z cuadrada es " ı + Math . if ( x > 0) throw ( new System .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. x = double .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 . Por ejemplo. las cuales deben ser objetos de la o clase Exception. o Ejemplo 3. Dise˜ o por Contrato: Asertos y Excepciones n 3. . } o } } C´digo 3. el lanzamiento de una excepci´n pasa cierta informaci´n a los manejao o dores. . } catch ( Exception 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.3.3: Ejemplo del relanzamiento de excepciones o Conceptualmente. . . LanzaMsg () . 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. } catch ( Exception e ) { Console . 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 . WriteLine (" Excepci´ n recapturada " + e ) . 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. public class ReLanzaExcepcion { public static void LanzaMsg () { try { . pero con frecuencia ´stos no precisa de dicha informaci´n. El bloque try m´s interno en el que se lanza una excepci´n es empleado a o para seleccionar la sentencia catch que procesar´ dicha excepci´n. // Relanzamiento } } public static void Main () { try { . .1. Sin embargo. WriteLine (" Primera captura " + e ) .3 muestra un ejemplo del relanzamiento de excepciones.3 El c´digo 3. throw new Exception (" Lanzada en LanzaMsg ") . . . throw . En este caso ser´ o ıa apropiado “empaquetar” la informaci´n en un objeto derivado de una clase Exception ya o existente. . .20 Tema 3. . . Lanzamiento de excepciones Mediante la expresi´n throw se lanzan excepciones. . el usuario probablemente querr´ informaci´n adicional por pantalla para a o seleccionar o ayudarle a decidir la acci´n a realizar por el manejador.

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

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

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

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

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

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

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

} public void Tick () { Reset (++ totSecs ) . secs ) . Esta pr´ctica com´n a a u evita que el operador sobrecargado tenga un orden prefijado en sus operandos. hours = ( i / 3600) % 24. totSecs ) . days = i / 86400. } public static MyClock operator ++( MyClock c ) { c . class MyClock { public MyClock () { } public MyClock ( unit i ) { Reset ( i ) . } private uint totSecs = 0 .5 El c´digo 4. totSecs + c2 . MyClock c ) { return new MyClock ( m * c . Obs´rvese como en la l´ e ınea 32 se vuelve a definir el operador ‘*’. } public static MyClock operator +( MyClock c1 . secs = 0 . pero con los par´metros en orden inverso. tanto unarios. secs = i % 60. o como binarios. } public static MyClock operator *( MyClock c . } public override string ToString () { Reset ( totSecs ) . mins = 0 . MyClock c2 ) { return new MyClock ( c1 . } public void Reset ( unit i ) { totSecs = i .1 muestra un ejemplo de sobrecarga de operadores. hours . totSecs ) . El resultado mostrado por pantalla tras ejecutarse el m´todo Main() ser´ e ıa: Initial times day 00 time:00:00:59 day 01 time:23:59:59 One second later day 00 time:00:01:00 day 02 time 00:00:00 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 using System . days . previamente sobrecargado por el m´todo de la l´ e ınea 29. mins . Herencia Ejemplo 4. uint m ) { return ( m * c ) . hours = 0 . } public static MyClock operator *( uint m . Tick () . return c . days = 0. mins = ( i / 60) % 60. } .28 Tema 4. return String . Format (" day {0: D2 } time :{1: D2 }:{2: D2 }:{3: D2 }" .

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

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

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

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

que no la llevan. } int Edad { get . Las tres son implementadas por la clase Ayudante. } string Nss { get . } set { edad = value . } // N o seguridad social } class Ayudante : IPersona .4 se muestra un ejemplo de una interface IPersona. } n } interface IProfesor : IPersona { double Salario { get . set . set . IEstudiante . n n } } .9 En el c´digo 4. o Figura 4.5 Clases Diferidas 33 Ejemplo 4. } } public int Edad { get { return edad . Obs´rvese el convenio de nombrar a las interfaces con una ‘I’ may´scula delante del e u nombre. } set { telefono = value . } set { notaMedia = value .5: Herencia e implementaci´n de interfaces o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 interface IPersona { string Nombre { get . } bool esMayorDeEdad () . set . La figura 4. set . set . } } public bool esMayorDeEdad () { return ( edad >= 18) . } int A~ oMatricula { get . a diferencia de las clases.4. IProfesor { // M´ todos y propiedades requeridos por IPersona e public string Name { get { return name . } set { name = value . } set { a~ oMatricula = value . } string Telefono { get .5 muestra el esquema de herencia e implementaci´n de las interfaces y la clase o en cuesti´n. } } public int A~ oMatricula n { get { return a~ oMatricula . set . de la cual o heredan otras dos interfaces IEstudiante e IProfesor. } } public string Telefono { get { return telefono . } interface IEstudiante : IPersona { double NotaMedia { get . } // M´ todos y propiedades requeridos por IEstudiante e public double NotaMedia { get { return notaMedia . set .

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

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

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

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

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

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

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

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

42 ´ INDICE DE FIGURAS .

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

44 ´ INDICE DE TABLAS .

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

46 ´ ´ INDICE DE CODIGOS .

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

Sign up to vote on this title
UsefulNot useful