Download Introducción a la Orientación a Objetos
Transcript
Introducción a la Orientación a Objetos Fernando Bellas Permuy Departamento de Tecnologías de la Información y las Comunicaciones (TIC) Universidad de A Coruña http://www.tic.udc.es/~fbellas fbellas@udc.es Ciclo de vida de una aplicación Análisis Diseño Implementación Pruebas Mantenimiento Distintas formas de construcción de sistemas software • Programación estructurada. – C, Pascal, Modula. • Programación funcional. – Lisp, Cammel. • Programación lógica. – Prolog. • Programación orientada a objetos. – Smalltalk, Eiffel, C++, Java. • Programación con agentes. El paradigma de los objetos (1) • Un sistema software es un conjunto de objetos que cooperan. – Ej.: en un editor de gráficos: cuadrado, círculo, línea, imagen, barra de herramientas, etc.). • Los objetos poseen una funcionalidad (operaciones que son capaces de hacer o mensajes a los que son capaces de reaccionar). – Ej.: Dibujar, CambiarTamanho , Mover, Eliminar, etc. El paradigma de los objetos (y 2) • El diseño orientado a objetos es un paradigma opuesto a una visión algorítmica (descomposición funcional) del sistema implementar. Proceso () { SubProceso1(); … SubProcesoN(); } Dibujar Cuadrado Barra de Selección Circulo Linea Descomposición funcional vs orientación a objetos Descomposición funcional Orientación a objetos • Módulos construidos alrededor de las operaciones. • Datos globales o distribuidos entre módulos. • Entrada/Proceso/Salida. • Organigramas de flujo de datos. • Módulos construidos alrededor de las clases. • Clases débilmente acopladas, y sin datos globales • Encapsulación/mensajes. • Diagramas jerárquicos de clases. Ventajas de la orientación a objetos • Un diseño orientado a objetos maximiza la: – Modularidad y encapsulación • El sistema se descompone en objetos con unas responsabilidades claramente especificadas. – Extensibilidad • Posibilidad de ampliar la funcionalidad de la aplicación de manera sencilla. – Reusabilidad • Posibilidad de reutilizar parte del código para el desarrollo de una aplicación similar. Concepto de clase (1) • Una clase describe un conjunto de ejemplares con propiedades y comportamientos similares. • Una clase se describe por: – Nombre. – Interfaz: Operaciones (métodos, mensajes) que manipulan el estado. – Conjunto de atributos (datos) que definen el estado. • Desde el punto de vista de la programación una clase es un tipo (ejs.: Rectangulo, Lista, Cola, NumeroComplejo, etc.). Concepto de clase (y 2) Nombre Rectangulo Interfaz void Dibujar () void Ocultar () void Mover (float nuevaCoordX, float nuevaCoordY) void CambiarDeTamanho (float nuevoAncho, float nuevoAlto) float Area () float DameCoordX () float DameCoordY () float DameAncho () float DameAlto () Atributos float coordX, coordY float ancho, alto return alto*ancho; Prototipo (signature) Concepto de objeto • Objeto (instancia): cada uno de los ejemplares de una clase. • Desde el punto de vista de la programación, un objeto es una variable. X Y Tipos de operaciones • Constructor: crea una instancia de la clase. • Destructor: destruye una instancia. • Selector: selecciona una parte del estado o devuelve una propiedad resultante de la combinación de algunos atributos. – Ejs.: DameCoordX, DameCoordY, DameAncho , DameAlto, Area , etc. • Modificador: modifica una parte del estado según algún criterio. – Ejs.: Mover , CambiarDeTamanho, etc. • Copiador: copia un objeto en otro. • Iterador: permite recorrer una estructura de datos (ej.: para recorrer una lista). • Visualizador: muestra todo el estado del objeto de una forma elaborada. – Ej.: Dibujar. Envío de mensajes • Un objeto de una clase responde a cualquiera de los mensajes definidos en la clase. – float coordX = unRectangulo.DameCoordX(); – unRectangulo.Mover(0, 20); – unRectangulo.Dibujar(); Encapsulación • • Los clientes de una clase sólo conocen la interfaz de la misma, es decir, conocen los prototipos de las operaciones pero no cómo están implementadas. Por tanto, si la implementación de una clase varía, y la interfaz continúa siendo la misma, no es necesario cambiar el código de los clientes. NumeroComplejo NumeroComplejo NumeroComplejo Sumar (NumeroComplejo c) NumeroComplejo Restar (NumeroComplejo c) NumeroComplejo Multiplicar (NumeroComplejo c) NumeroComplejo Dividir (NumeroComplejo c) NumeroComplejo Sumar (NumeroComplejo c) NumeroComplejo Restar (NumeroComplejo c) NumeroComplejo Multiplicar (NumeroComplejo c) NumeroComplejo Dividir (NumeroComplejo c) float DameModulo () float DameArgumento () float DameParteReal () float DameParteImaginaria () float DameModulo () float DameArgumento () float DameParteReal () float DameParteImaginaria () float modulo, argumento float parteReal, parteImaginaria Visibilidad • Los atributos y operaciones pueden tener los siguientes tipos de acceso (visibilidad): – Público • Se pueden acceder desde cualquier clase. – Privado • Sólo se pueden acceder desde operaciones de la clase. – Protegido • Sólo se pueden acceder desde operaciones de la clase o de clases derivadas. • Norma general: – El estado debe ser privado. – Las operaciones que definen la funcionalidad deben ser públicas. – Las operaciones que ayudan a implementar parte de la funcionalidad deben ser privadas (si no se utilizan desde clases derivadas) o protegidas (si se utilizan desde clases derivadas). Relación de herencia (1) • Permite definir una clase hija (subclase) a partir de una clase padre (base, superclase). • La clase hija hereda el interfaz (con la implementación de las operaciones) y los atributos. • Relación “es un”. Relación de herencia (2) Ser Nacer () Morir () Animal aci Sentir () aliz Vegetal eci r ón Esp ón G e en iz al i ac Mamifero Ave Volar () Relación de herencia (3) • Concepto de tipo: un tipo denota una interfaz particular. – Ej.: Ser , Animal , Vegetal, etc. • Un tipo es un subtipo de otro si su interfaz contiene la interfaz de su supertipo. – Ej.: Animal es un subtipo de Ser y un supertipo de Ave y Mamifero. • Diferencia entre los conceptos de clase e interfaz. – El concepto de clase hace referencia a los atributos y a las operaciones, junto con su implementación. – El concepto de interfaz hace referencia sólo a los prototipos de las operaciones visibles. • En un lenguaje orientado a objetos siempre se pueden hacer asignaciones del estilo supertipo = subtipo entre instancias. – unAnimal = unAve, pero NO unAve = unAnimal. Relación de herencia (4) • La clase hija puede extender o redefinir (override) el comportamiento de la clase padre. – Extensión: Se añaden operaciones y/o atributos (ej.: Volar en el caso de Ave). – Redefinición: Se cambia la implementación de alguna operación heredada (o se le da una implementación si no la tenía). Relación de herencia (5) Texto Cargar () Grabar () Presentar () PostScript Presentar () Presentar ASCII HTML Procesar PostScript Presentar () Procesar HTML Relación de herencia (6) • Clase abstracta – Deja sin definir una o más operaciones (sólo declara sus prototipos), que se definirán en subclases. Estas operaciones se denominan operaciones abstractas. – No se pueden crear instancias de una clase abstracta. – Su objetivo es especificar una interfaz común para todas sus subclases. • Clase concreta – Una clase que no es abstracta, es decir, que no define operaciones abstractas y define las operaciones abstractas que hereda. Relación de herencia (7) • Un ejemplo de clase abstracta (Figura) ... Grafico Figura Insertar (Figura) Dibujar () Area () Mover () Ocultar () Dibujar () Area () Mover () Ocultar () Rectangulo Circulo Triangulo Dibujar () Area () Mover () Ocultar () Dibujar () Area () Mover () Ocultar () Dibujar () Area () Mover () Ocultar () Relación de herencia (8) • Un ejemplo de clase abstracta (continuación) Cuadrado* unCuadrado = << Crear instancia de “Cuadrado”. >> Circulo* unCirculo = << Crear instancia de “Circulo”. >> Triangulo* unTriangulo = << Crear una instancia de “Triangulo”. >> Grafico* grafico = << Crear una instancia de “Grafico”. >> grafico->Insertar(unCuadrado); grafico->Insertar(unCirculo); grafico->Insertar(unTriangulo); grafico->Dibujar(); Relación de herencia (9) • Un ejemplo de clase abstracta (continuación) void Grafico::Dibujar () { IteradorFiguras i; i = ObtenerIteradorFiguras(); while (! i.Fin()) { Figura* figura = i.Elemento(); figura->Dibujar(); i.Siguiente(); } } • El código de Dibujar no depende de los tipos de figura que haya. – Se evita código case/switch, es decir ... Relación de herencia (10) Grafico_Dibujar (Grafico* grafico) { while (! Lista_Fin(grafico->figuras) ) { struct FiguraYTipo figuraYTipo = Lista_Actual(grafico->figuras); switch (figuraYTipo.tipo) { case EsRectangulo: Rectangulo_Dibujar((Rectangulo*)figuraYTipo.figura); break; case EsCirulo: Circulo_Dibujar((Circulo*)figuraYTipo.figura); break; case EsTriangulo: Triangulo_Dibujar((Triangulo*)figuraYTipo.figura); break; } Lista_Siguiente(grafico->figuras); } } Relación de herencia (11) • Polimorfismo: Distintas instancias del mismo tipo interpretan un mismo mensaje de distinta forma. – Ej.: En la implementación de Grafico::Dibujar existe polimorfismo (figura.Dibujar()). – El polimorfismo requiere enlace dinámico. • Enlace dinámico: La llamada a figura.Dibujar se resuelve en tiempo de ejecución. • Enlace estático: La llamada a grafico.Dibujar se resuelve en tiempo de compilación. • Consejo: Programar haciendo uso de una interfaz, y no de una implementación concreta. Relación de herencia (12) • Herencia de implementación: La clase hija hereda la implementación de métodos de la clase padre. – Ej.: el ejemplo de la jerarquía de los seres vivos. • Herencia de interfaz: La clase hija hereda el interfaz (pero no la implementación de las operaciones). – Ej.: el ejemplo de la jerarquía de figuras. • Algunos lenguajes tienen palabras clave para distinguir entre herencia de interfaz y clase (ej.: Java), mientras que otros no (ej.: C++). • Herencia de clase: combina la herencia de implementación y de interfaz. – Ej.: siguiente transparencia ... Relación de herencia (13) ColeccionTextos Insertar (Texto) Pesentar () Texto Cargar () Grabar () Presentar () forall t in Textos t.Presentar() ASCII Presentar () Presentar ASCII PostScript Presentar () Procesar PostScript HTML Presentar () Procesar HTML Relación de herencia (14) • Métodos plantilla … Documento Grabar () Abrir () Cerrar () Leer () Aplicacion AnhadirDoc () AbrirDoc () CrearDoc () PuedoAbrirDoc () ApuntoDeAbrirDoc () MiDocumento Leer () MiAplicacion CrearDoc () PuedoAbrirDoc () ApuntoDeAbrirDoc () if (! PuedoAbrirDoc(nombre)) { return; } Documento* doc = CrearDoc(); if (doc) { docs->AnhadirDoc(doc); ApuntoDeAbrirDoc(doc); doc->Abrir(); doc->Leer(); } Relación de herencia (15) • Herencia múltiple – una clase hija hereda de dos o más padres. – No está disponible en todos los lenguajes (disponible en C++; en Java sólo para la herencia de interfaz). VehiculoTerrestre VehiculoAcuatico DesplazarsePorTierra () DesplazarsePorAgua () VehiculoAnfibio Relación de herencia (y 16) • Herencia múltiple (continuación) – Problema de ambigüedad: unVehiculoAnfibio.Desplazarse(); VehiculoTerrestre VehiculoAcuatico Desplazarse () Desplazarse () VehiculoAnfibio - Los lenguajes ofrecen mecanismos para deshacer la ambigüedad (en C++ => unVehiculoAnfibio.VehiculoTerrestre::Desplazarse()). Relación de composición/agregación (1) • Un Grafico se compone de varios objetos Figura. Grafico Figura Insertar (Figura) Dibujar () Area () Mover () Ocultar () Dibujar () Area () Mover () Ocultar () forall f in Figuras f.Dibujar (); Rectangulo Circulo Triangulo Dibujar () Area () Mover () Ocultar () Dibujar () Area () Mover () Ocultar () Dibujar () Area () Mover () Ocultar () Relación de composición/agregación (y 2) • El código de los métodos del agregado (Grafico) delega parte de su implementación en métodos de sus partes (Figura). • El agregado puede tener la responsabilidad de liberar la memoria de sus partes (ejemplo anterior) o no (siguiente ejemplo). Reutilización de código: herencia de clase vs composición (1) Rectangulo Area () Figura Ventana Area () DarForma (Figura) Area () Figura forma Ventana forma.Area() Rectangulo Circulo Area () Area () float ancho float alto float radio return ancho*alto; return PI * radio 2; Reutilización de código: herencia de clase vs composición (2) Ventaja Desventaja Herencia • Fácil de utilizar. • Fácil de modificar la implementación heredada. • Establece relaciones estáticas. • Se rompe la encapsulación. Composición • Establece relaciones dinámicas. • Se mejora la encapsulación. • Mayor número de objetos. • El comportamiento del sistema depende de las relaciones entre objetos, en vez de estar concentrado en una clase. Reutilización de código: herencia de clase vs composición (y 3) • Consejos : • Favorecer la composición frente a la herencia de clase. • Evitar excesivas relaciones entre clases (las clases deben estar débilmente acopladas). • Evitar jerarquías de clases excesivamente complejas. • Un último consejo: Think simple ! Recursos • Libros • E. Gamma, R. Helm, R. Johnson, J. Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software, Addisson-Wesley, 1994. • Página web del curso • http://www.tic.udc.es/~fbellas