Download Introducción a la Orientación a Objetos

Document related concepts

Polimorfismo (informática) wikipedia , lookup

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
[email protected]
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