Tres elementos esenciales de la programación orientada a objetos

Anuncio
Tres elementos esenciales de la
programación orientada a objetos
„
„
„
Abstracción
Herencia
Polimorfismo
Objetos
Modelado en objetos
„
importancia del diagrama de clases:
– es el diagrama esencial para UML
– es el depositorio central de la información acerca
del sistema
– refleja el mundo real y la visión que se tiene acerca
de él
– es menos dependiente de detalles que el MDF y que
los diagramas dinámicos
– posee estabilidad con la evolución
– organiza el mundo real en elementos manejables
„
casos de uso en el modelado en objetos
Objetos
Dr.
Dr.Deni
DeniTorres
TorresRomán:
Román:
1
Tareas para el modelado en objetos
„
„
„
„
recopilación de información: casos de uso
definir diagrama de contexto: actores-sistema
identificar candidatos a objetos: sustantivos en los
casos de uso
seleccionar clases:eliminar redundancia, vaguedad,
irrelevancia; atributos, operaciones, roles; eventos;
lo no perteneciente al mundo real
„
crear diagrama de clases
„
identificar relaciones: agregación, dependencia,
herencia, asociación reflexiva
determinar atributos y operaciones
refinar el modelo para herencia: jerarquía
probar el modelo: casos de uso, diccionario del
modelo
„
„
„
Empaquetamiento
„
„
„
„
„
„
„
sistemas grandes necesitan ser particionados para
lograr visibilidad y manejar la complejidad
agrupamiento de objetos ayuda a crear diferentes
niveles de abstracción
un sistema es una colección de paquetes
un paquete es un agrupamiento lógico de
elementos del modelo ( clases , casos de
uso,procesadores,...) con alta cohesión y bajo
acoplamiento
un paquete puede ser descompuesto en otros
un paquete puede ser visto como un subsistema o un
módulo
Ejemplos:
Objetos
2
Operador de referencia &
„
„
„
„
una referencia es un alias
necesita, a diferencia de un puntero, ser siempre
inicializada
una referencia contiene una dirección pero se
comporta como un valor
Ejemplo
–
–
–
–
–
–
int valor = 50;
int &refValor = valor;
int &refValor2;
refValor +=5;
int otroValor = refValor;
int *ptr = &refValor;
//declaración de la referencia
//ERROR en “
“ “
//valor = 55
// otroValor = 55
// incializa al puntero
// con la dirección de valor
Objetos
Llamadas por valor, puntero y referencia
„
void Cambio (int a, int b) {
int local = a;
a = b;
b = local;
}
„
void Cambio (int *pa, int *pb) {
int local = *pa;
*pa = *pb;
*pb = local;
}
„
//Cambio (x, y);
//Cambio (&x, &y);
void Cambio (int &a, int &b) {
int local = a;
a = b;
b = local;
}
//Cambio (x, y);
3
Operador de resolución de ámbito ::
Ejemplo
#include <iostream.h>
int a;
void main() {
float a = 1.5;
::a = 5;
cout<<“local a”<< a <<endl;
cout<<“global a”<< ::a <<endl;
}
::variable permite el acceso a un elemento oculto en el
ámbito actual
Objetos
Estructura específica de los datos de
una clase
class NombreDeLaClase {
private:
int datoInt;
char* chPtr;
protected:
object* objectPtr;
public:
struct nombreStructure;
};
„
características de cada tipo de dato
Objetos
4
Estructura específica de las
funciones miembros de una clase
ret NombreDeLaClase::NombreDelMetodo
{
cuerpo
//código
}
„
„
„
las funciones miembros o métodos pueden ser
también private, protected y public
las funciones miembros pueden ser: modificadoras,
selectoras e iteradoras
métodos selectores
– ret NombreDelMetodo const;
Objetos
Dr.
Dr.Deni
DeniTorres
TorresRomán:
Román:
La biblioteca iostream
„
„
„
„
iostream vs stdio
cout y cin objetos que permiten mediante el
operador <<(>>) la salida o entrada de datos
objetos flujos de datos
Ejemplos
–
–
–
–
„
cout<<“imprime un entero”<<15<<endl;
cout<<“imprime un flotante”<<15.25<<endl;
cout<<“imprime un letrero”<<endl;
cout<<“imprime un hexadecimal”<<0xA5<<endl;
Diferencias entre cout y printf
Objetos
5
Asignación dinámica de memoria new
„
„
„
En C existen las funciones malloc() y free()
En C++ new asigna memoria dinámica
– new tipo; // asigna un solo elemento
– new tipo [ ]; // asigna un arreglo de elementos
Ejemplos
int n;
char* s;
cin>>n;
int *p = new int;
s = new char [n];
Point *p1= new Point(...);
Objetos
Liberación dinámica de memoria delete
„
„
En C existe la función free()
En C++ delete libera memoria dinámica
– delete dirección;
// libera un espacio
// previamente asignado por new
– delete[n] dirección; // idem para un arreglo de
// elementos
„
Ejemplos
delete p;
delete [ ] s;
delete p1;
Objetos
6
Ventajas de new y delete
„
„
„
„
new conoce cuanta memoria se le asigna a
cada variable, pero malloc( ) no,
new invoca al constructor del objeto, mientras
que malloc( ) no puede,
delete invoca al destructor y libera memoria.
siempre que use un new debe emplear en la
parte correspondiente un delete para liberar
memoria, p.e. constructor/destructor
Objetos
Funciones inline
„
„
„
„
„
„
el compilador genera el código cada vez que
encuentra esta función, es más segura que #define
#define cuadrado (x) x*x
– errónea si x= a+b
sólo tiene sentido para funciones de código pequeño,
aumenta la eficiencia del programa,
no deben definirse donde se hace la definición de la
clase, porque allí no debe haber código,
Sintaxis
– inline ret NombreDeFunción ( args ) { }
Objetos
7
Declaraciones y definiciones en un
archivo.h
„
„
„
„
„
„
„
definiciones de tipo
definiciones de
funciones
declaraciones de datos
includes
macro-definiciones
comentarios
declaraciones de clases
„
„
„
„
„
„
„
struct point {...}
extern int strlength(...)
extern int a;
#include <signal.h>
#define ....
/*...*/
//
class clase {...};
Objetos
Herencia y reusabilidad
„
creación de clases a partir de otras para
extender y reusar el código
– los objetos pueden construirse de modo
incremental a partir de otros objetos y pueden
compartir código y estructuras de datos
– los algoritmos generales se pueden escribir de
modo que se puedan reusar para nuevos tipos de
objetos
„
„
organización jerárquica
representación del polimorfismo
Objetos
Dr.
Dr.Deni
DeniTorres
TorresRomán:
Román:
8
Clases base y derivadas
„
„
„
clases con similares atributos y operaciones
pueden organizarse jerárquicamente
la clase situada arriba de otras es base o
superclase de las de abajo
la clase situada abajo de otras es derivada o
subclase
ANIMAL
Generalización
„
Definición
– proceso de extracción de todos los atributos y
operaciones comunes en un conjunto de clases
para crear una clase base o superclase
„
Ejemplo
– atributos: tipo, modelo, capacidad,...
– operaciones: arrancar, parar, acelerar,...
VEHICULO
9
Especialización
„
Definición
– proceso de refinamiento de clases en subclases
o clases derivadas que heredan atributos y
operaciones de la clase base o superclase
„
Ejemplo
Operación extra:
flotar
Atributo extra:
Número de ruedas
Terrestre
Acuático
Objetos
Concepto de herencia simple
Clase Base
Clase Derivada 1
Clase Derivada 2
Clase Base
Clase Base
Objetos
10
Especificadores de acceso
„
„
„
„
„
„
class B : public class A {
};
los miembros public y protected de A pasan de
igual forma a B
class B : private class A {
};
los miembros public y protected de A pasan en
forma private a B
class B : protected class A {
};
los miembros public y protected de A pasan en
forma protected a B
Elementos en la herencia (I)
private
protected
A
public
private A
private B
protected A
protected B
public A
B
public B
Objetos
11
Elementos en la herencia (II)
„
„
„
B hereda las funciones de A
B hereda los datos de A
las funciones propias de B no tienen
acceso a los miembros private de A
Objetos
Concepto de herencia múltiple
Clase B
Clase A
Clase Derivada AB
Objetos
12
Relaciones multiniveles de herencia
entre clases
Clase A
Clase C
Clase B
Clase D
Clase E
Objetos
Elementos que no se heredan
„
„
„
„
„
„
constructores
destructores
funciones friend
funciones static
datos static
operador de asignación =
Objetos
13
Conversiones de herencia
„
„
„
un objeto de una clase derivada se
convierte implícitamente en un objeto de
una clase base pública,
una referencia a una clase derivada se
convierte implícitamente en una referencia
a una clase base pública,
un puntero a una clase derivada se
convierte implícitamente en un puntero a
una clase base pública.
Objetos
Dr.
Dr.Deni
DeniTorres
TorresRomán:
Román:
Polimorfismo
„
„
„
„
Sobrecarga de funciones
Sobrecarga de operadores
Funciones virtuales
Funciones virtuales puras
Objetos
14
Polimorfismo (I)
una operación que puede tener más de un método es
denominada polimórfica
una operación se dice polimórfica si se comporta de
forma diferente sobre clases diferentes
la lista de argumentos, el tipo de retorno asociados
con una operación constituyen el formato o signatura
de la operación
las operaciones polimórficas tienen el mismo
nombre, la misma intención lógica y la misma
signatura
las operaciones polimórficas tienen o pueden tener
código diferente en clases diferentes
„
„
„
„
„
Objetos
Polimorfismo (II)
„
objetos de clases diferentes responden a un
mismo mensaje u operación de forma también
diferente
– objetos de las clases circulo, triángulo, rectángulo,
derivados de la clase forma, pueden responder a la función
área() de forma diferente
„
„
„
característica esencial del polimorfismo es que se
puedan invocar funciones sin preocuparnos
sobre qué tipo de objeto son invocadas
construcción de estructuras heterogéneas de
objetos debido a que un puntero a una clase base
puede apuntar a cual objeto de clases derivadas
el polimorfismo se implementa con funciones
denominadas virtuales
15
Sobrecarga de funciones: polimorfismo
„
„
¿Qué es una función sobrecargada?
Ejemplos
– int suma (int a, int b);
– string suma (string a, string b);
„
Las funciones sobrecargadas tienen:
–
–
–
–
„
el mismo nombre,
un número diferente de argumentos,
diferentes tipos de argumentos,
ambas cosas
Las funciones sobrecargadas pueden ser
normales o miembros de una clase
Objetos
Ventajas de la sobrecarga de
funciones
„
„
„
„
„
uso del polimorfismo,
menor número de nombres de funciones,
sintaxis más clara,
el compilador hace mucho de nuestro trabajo,
enlace dinámico con funciones virtuales,
llamadas en tiempo de ejecución.
Objetos
Dr.
Dr.Deni
DeniTorres
TorresRomán:
Román:
16
Sobrecarga de operadores
„
en C++ significados de +:
– suma de dos enteros
– suma de dos reales
„
si a y b son dos objetos definidos por el usuario,
¿será o no posible definir las operaciones de:
– a = a + b;
– a = a*b;
„
?
la sobrecarga permite la validez de las
expresiones anteriores. Con el operador +
sobrecargado podríamos formar una cadena a
partir de otras, p.e.
– “Guadalajara” + “es la capital” + “de Jalisco.”
„
tipos de operadores:
– unarios
– binarios
Objetos
Restricciones en los operadores
sobrecargados de C++
„
„
„
„
„
„
se pueden sobrecargar sólo los operadores definidos
en C++; no se pueden construir nuevos operadores
la sobrecarga tiene validez sólo con objetos de la
clase donde el operador está definido
no se puede cambiar la preferencia o asociatividad
de los operadores en C++
no se puede cambiar un operador binario para que
funcione como uno unario y viceversa
no se puede sobrecargar un operador que funcione
exclusivamente con punteros
la sobrecarga de ++ y -- no diferencia, en principio,
pre- o postincremento
Objetos
17
Sintaxis general de operator
„
función miembro o método de la clase
– class unTipo {
private: atributos
public:
unTipo operator <op> (lista de argumentos);
....
};
„
implementación del método o función miembro
– unTipo unTipo::operator <op> (lista de argumentos)
{
cuerpo de la función
}
„
„
al menos un operando debe ser un tipo definido por el
usuario, p.e. unTipo
un operando puede ser un tipo básico
Sobrecarga de operadores binarios (I)
„
X1 + x2 se interpreta como
– operator + ( x1, x2 ); // o como
– x1.operator + ( x2 );
„
un operador unario se puede definir como:
– una función miembro de un argumento
– una función friend con dos argumentos
„
class Binario {
public:
Binario operator <op> (Binario& );
};
Binario Binario::operator <op> (Binario& b ) {
cuerpo
}
<op> puede ser +, *, -, /,...
18
Sobrecarga de operadores binarios (II)
„
Ejemplo:
– class unaClase {
public:
unaClase operator -(unaClase &t);
unaClase operator -(int t);
// unaClase- unaClase
// unaClase- int
};
– class unaClase {
private:
int undato;
public:
friend ostream& operator << ( ostream &, const unaClase & );
};
ostream& operator << ( ostream &out, const unaClase &t ) {
out << “Salida en pantalla “<<endl<<“ dato privado =“
}
<< t.undato <<endl;Objetos
Sobrecarga de operadores unarios
„
++ se interpreta como
– operator ++ ( x ); // o como
– x.operator ++ ( );
„
un operador unario se puede definir como:
– una función miembro sin argumentos
– una función friend con un argumento
„
Ejemplo
– class unaClase {
public:
unaClase& operator ++ ( void );
// ++unaClase
};
– class unaClase {
public:
friend unaClase& operator ++ ( unaClase& );
Objetos
};
//++ unaClase
19
Recomendaciones para sobrecargar
los operadores
„
„
„
„
„
es responsabilidad del programador definir
correctamente el significado de las funciones
sobrecargadas, pues C++ no interpreta
automáticamente el significado de un operador
sobrecargado
C++ no deriva automáticamente el significado de un
operador complejo, p.e.+=,
no se puede cambiar la sintaxis de los
operadores, p.e. + binario, ++ unario
sólo se pueden sobrecargar los operadores
indicados por C++
no se puede cambiar la precedencia o prioridad de
los operadores
Objetos
Ejemplos de sobrecargas de
operadores válidas y no válidas
„
„
complejo operator + (complejo a, complejo b); //VAL
void contador::operator++ (contador c)
//VAL
{
„
„
„
}
char* operator + (char* a, char* b);
//NO VAL
void operator@ (menu barra1, menu barra2); //NO VAL
menu operator++ (menu barra1, menu barra2); //NO VAL
Objetos
20
Sobrecarga del operador de asignación =
„
el operador de asignación = puede sobrecargarse
declarando una función miembro
class string {
string& operator = (string& str);
};
„
„
si el operador = no se define por el usuario en
una clase, entonces el compilador lo crea por
defecto y realiza una asignación miembro a miembro
x& x::operator = (const x& fuente)
{
cuerpo
}
Objetos
Sobrecarga de los operadores de llamada a
funciones ( ) y de subíndice [ ] y de flujo >> y <<
„
el operador ( ) puede emplearse para un tipo de
subconjunto de la clase, p.e., un substring de la
clase string
– string string::operator( ) (int pos, int cont)
„
el operador [ ] puede emplearse para extraer
elementos específicos de un objeto de la clase, p.e.,
un caracter de un objeto de la clase string
– char& string::operator[] (int elem)
„
la sobrecarga de los operadores >> y << permite
manipular además de los tipos de datos
predefinidos, los tipos definidos por el usuario
Objetos
21
El apuntador this
„
el llamado a funciones se realiza siempre mediante un
objeto
–
–
–
–
„
„
„
objeto.funciónDeLaClase ( ); // o mediante un puntero
punteroObjeto-> funciónDeLaClase ( );
¿cómo se realiza esto?
funciónDeLaClase ( this, argumentos );
en todo objeto existe un puntero al objeto llamado this
this accesa a la dirección del propio objeto
this permite accesar a los miembros del propio objeto
– this ->nombreDeMiembro;
„
*this es el objeto total real, no modificable
Uso del this
„
„
almacenar un puntero al objeto asociado con la
invocación de una función miembro
devolver una referencia al objeto asociado con la
invocación de una función miembro
T& T::f (int a )
código
return *this;
}
„
„
hacer copias de un objeto
referenciar explícitamente a un miembro oculto
como resultado de otra declaración
–
–
–
–
„
{
class X {
int longitud;
public:
X (int longitud){this -> longitud = longitud;}
como argumento de una función
22
Constructor de copia
„
Descripción
– un constructor que crea un nuevo objeto a partir de uno
existente
„
Sintaxis
class Point {
int x, y;
public:
Point (int, int);
Point (const Point&);
...
};
„
Implementación
Point::Point (const Point& p)
x=p.x;
y =p.y;
{
}
Constructor de copia por defecto
„
„
si no se incluye un constructor de copia el
compilador crea uno automáticamente
constructor de copia por defecto realiza las
siguientes operaciones
– void main() {
– Point p1(1,2), p2(3,4), p3,;
– Point p4(p2);
p4.x = p2.x;
p4.y = p2.y;
„
//FUNCIONA MUY BIEN
//SIN DEFINIRLO, ENTONCES?
si un dato fuera un puntero, p.e., entonces se copia
la dirección del puntero de la derecha en el miembro
de la izquierda
– p4.ptr = p2.ptr;
– LOS DOS APUNTAN AL MISMO LUGAR!!!
23
Llamadas a los constructores de copia
„
„
„
„
inicialización de un objeto con otro de la misma
clase
cuando se tiene una función con un argumento
siendo un objeto
cuando una función retorna un objeto
Regla sobre el uso del constructor de copia
– las clases con estructuras dinámicas de datos
deben tener bien definido un constructor de copia,
pues los constructores de copia por defecto sólo
generan una copia superficial y no una copia
profunda
Dr.
Dr.Deni
DeniTorres
TorresRomán:
Román:
Objetos
Inicialización de objetos en C++
„
„
„
Los datos o miembros de
un objeto se inicializan
con valores
la incialización se realiza
en los constructores
formas de inicializar
– incialización mediante
„
Ejemplo:
class ObjetoIni {
string s:
char* dato;
ObjetoIni (const string&,
const char* iniCh);
};
„
sentencias
ObjetoIni::ObjetoIni (const
string& iniStr, const char*
iniCh){
s = iniStr;
dato = iniCh;}
lista de incialización
„
ObjetoIni::ObjetoIni (const
string& iniStr, const char*
iniCh):s(iniStr, dato (iniCh){ }
Objetos
24
Uso del operador =
Ejemplo
„
string a(“Hola”);
sttring b(“Nada”);
a =b;
// Ahora a contiene la expresión “Nada”
– el compilador creó el =, pero es una copia superficial !!!
forma correcta de definirlo
„
string& string::operator = (const string& s) {
if (this ==&s) return *this; // a==a CASO IDENTIDAD
delete [ ]str;
//BORRAR VIEJO CONTENIDO
long = s.long;
if (s.str!=NULL){
str = new char [long+1]; //COPIA
strcpy (str, s.str);}
//NUEVA
return *this;
Objetos
}
Enlace estático y dinámico
„
el enlace estático se realiza siempre que el
compilador conoce con antelación el tipo de objeto
– es rápida
– es restrictiva
„
Ejemplo: switch (codigo) {
– case ´A´: exit ();
– case ´B´: mostrar ();
break; }
„
el enlace dinámico se realiza siempre que el
compilador desconoce la posición a invocar hasta el
tiempo de ejecución
– alto grado de flexibilidad
– más lento que el estático
– uso de funciones virtuales mediante la palabra virtual
25
Sobre las funciones virtuales (I)
„
„
„
„
„
„
las funciones miembros de una clase pueden ser
virtuales
las funciones globales no pueden ser virtuales
los destructores de las clases que van a ser
heredadas deben declararse virtual para que sean
llamados por los destructores de las clases derivadas
¿para qué?
el uso de funciones virtuales puras posee gran
utilidad, ¿por qué?
en el interior de un constructor/destructor las
funciones virtuales se llaman en tiempo de
compilación
una clase con una función virtual pura es una clase
abstracta
Sobre las funciones virtuales (II)
„
„
„
„
la palabra clave virtual permite a una función ser definida en
la clase base y en las clases derivadas bajo el mismo nombre
una función sólo necesita ser declarada virtual en la clase
base
las funciones virtuales admiten los mismos argumentos,
pero código diferente en clases también diferentes
función virtual vacía
– virtual void FuncionVacia ( ) { }
„
función virtual pura
– virtual void FuncionPura ( ) = 0;
„
„
una función virtual pura no puede ser llamada en la clase
base
una función virtual pura sirve para declarar aquellas
funciones cuya definición se pospone para las clases
derivadas
26
Sobre las funciones virtuales (III)
los constructores no pueden ser virtuales
los destructores pueden y deben ser virtuales, lo cual
permite que en una relación de herencia sean invocados
todos los destructores
„
„
„
„
„
„
una clase abstracta es aquella que tiene al
menos una función virtual pura
una clase abstracta sólo puede ser utilizada como
clase base
una clase abstracta se diseña sólo para ser
heredada
las clases abstractas son utilizadas sólo a través
de punteros
Objetos
Polimorfismo en C++
„
crear una jerarquía de objetos con operaciones
definidas como funciones virtuales en la clase base
– virtual float Area ( );
„
si la clase base es tal que no se puede realizar
implementaciones de estas funciones, entonces son
funciones virtuales puras
– virtual float Area ( ) = 0;
– virtual float Area ( ) const = 0;
„
„
hacer las implementaciones concretas en las clases
derivadas; cada clase tiene una versión específica
de la función virtual
manipular las instancias de las clases a través
de una referencia o un puntero para provocar el
enlace dinámico
Objetos
27
Problema
„
Diseñar y elaborar un programa que
represente un reloj con hrs, min y segs y un
operator ++ que incremente el tiempo en
segundos. Debe existir una clase base y
clases derivadas para diferentes tipos de
relojes. Manejarse además funciones
virtuales.
Objetos
Casos de uso
„
características
– es una interacción entre un usuario y el
sistema
– captura alguna función visible al usuario
– puede ser de distintos tamaños
– satisface algún objetivo del usuario
– organiza el sistema mediante actores y
sus objetivos
– utilidad en el análisis, diseño y pruebas
Objetos
28
Casos de uso: partición del sistema
„
„
„
„
„
subconjuntos de los requerimientos
descripciones del comportamiento
grupos de entidades comunicantes
es fuente de las operaciones del sistema
conjuntos de escenarios potenciales
Objetos
Casos donde las funciones virtuales se llaman
en tiempo de compilación y no en tiempo de
ejecución o corrida
„
cuando una función virtual es llamada mediante
– objeto.FuncionVirtual ( ); //se le asocia la función actual
//de la clase base
„
„
en llamadas dentro de los constructores y destructores,
porque los objetos no están completamente inicializados
Ejemplo:
Objetos
29
Descargar