5 mecanismos reuntilizacion abstraccion
TRANSCRIPT
Mecanismos para la Reutilización y Abstracción del Código -1a
parte
Apoyo SSD5
Mtl Lourdes Cahuich 2
Objetivo
• Este módulo del curso presenta los mecanismos disponibles que facilitan la reutilización y abstracción del código en el lenguaje C++.
5.1 Herencia
Mtl Lourdes Cahuich 4
Un Mecanismo para la Abstracción y Reutilización del Código
• La herencia es un mecanismo en C++ (así como en Java) que facilita la reutilización y abstracción del código.
Mtl Lourdes Cahuich 5
Herencia
• Al usar la herencia, se pueden construir clases nuevas basadas en clases viejas, permitiendo que las clases hijo compartan las funciones y datos miembro de la clase padre.
• A través de estas relaciones surgen las ventajas de la abstracción de datos (generalización y especialización).
Mtl Lourdes Cahuich 6
Herencia
• En C++, una clase hijo hereda a todos los miembros no-privados de los datos incluyendo constructores.
• Una clase hijo en Java sin embargo, hereda de su clase padre a todos los miembros no-privados de los datos excepto constructores.
Mtl Lourdes Cahuich 7
Herencia
• En ambos lenguajes, las clases hijo heredan todos los miembros no-privados de los datos
Mtl Lourdes Cahuich 8
class BankAccount {protected:
double sum;string name;
public:BankAccount(string nm) : name(nm), sum(0) {}double balance() { return sum;}void deposit(double amount) {sum += amount;}void withdraw(double amount) {sum -= amount;}string get_name() { return name;}
};class SavingsAccount: public BankAccount {protected:
double rate;public:SavingsAccount(string nm)
: BankAccount(nm), // Call base class constructorrate(0.055) {}
void add_interest() {sum *= (1 + rate);}double get_rate() { return rate;}
};
Mtl Lourdes Cahuich 9
Herencia
• El listado anterior es un ejemplo de la herencia en C++ que demuestra como invocar métodos de una clase padre.
• En este listado, hemos definido una clase SavingsAccount que hereda de la clase BankAccount.
Mtl Lourdes Cahuich 10
Herencia
• La clase SavingsAccount provee una manera de añadir interés al dinero presentado en una cuenta
• La línea 23 invoca al constructor de la clase padre
• En C++ se usa el nombre de la clase padre seguida por los parámetros del constructor en paréntesis
Mtl Lourdes Cahuich 11
Niveles de herencia
• C++ tiene tres tipos, o niveles, de herencia: pública, privada y protegida.
• La herencia pública es el tipo más común de herencia usado en C++.
• Todos los ejemplos que hemos visto hasta el momento usan la herencia pública para modelar la relación "es un..." de dos clases.
Mtl Lourdes Cahuich 12
Niveles de herencia
• Las herencias privadas y protegidas modelan un tipo diferente de relación, llamada relación "usa un...".
• Para modelar que un carro usa un motor, podríamos heredar privadamente de la clase Engine al definir la clase Car.
Mtl Lourdes Cahuich 13
Niveles de herencia
• La forma más apropiada de modelar esta relación, sería que nuestra clase Car contenga una instancia de la clase Engine
• Modelar la relación "usa un..." de esta forma, es conocido como composición.
• Todos los usos de herencia en este curso se enfocan en las relaciones de modelación "es un...".
Polimorfismo
Mtl Lourdes Cahuich 15
Un Mecanismo para Abstracción
• Una característica fundamental de los lenguajes de programación orientados a objetos es el polimorfismo.
• Polimorfismo es la capacidad de un objeto de tomar diversas formas
Mtl Lourdes Cahuich 16
Polimorfismo
• En otras palabras, el polimorfismo permite que un programador se refiera a un objeto de una clase como un objeto de otra clase
• Esto tiene dos aplicaciones principales.
• Primero, podemos crear colecciones de objetos heterogéneos
Mtl Lourdes Cahuich 17
Polimorfismo
• Podemos operar en los objetos individuales de estas colecciones como si fueran todos del mismo tipo, sin que los objetos pierdan sus identidades reales
• En segundo lugar, podemos codificar algoritmos que hacen solamente suposiciones mínimas sobre los objetos que manipulan
Mtl Lourdes Cahuich 18
Polimorfismo
• Esto puede permitir que un algoritmo continúe funcionando correctamente aún cuando un programador introduce nuevas clases hijo en el sistema.
• Ambas aplicaciones ayudan a crear soluciones más duraderas
Mtl Lourdes Cahuich 19
Polimorfismo en C++
• Los programadores se pueden referir a objetos de una manera que facilite soluciones elegantes
• En C++, utilizamos funciones virtualesen conjunto con los apuntadores para tener acceso a objetos polimórficos
Mtl Lourdes Cahuich 20
Funciones virtuales
• Para ilustrar que funciones virtuales son y por que requerimos el uso de apuntadores en conjunto, veamos un ejemplo completo.
• Asume que deseamos implantar un sistema de gráficas que pueda desplegar varias formas geométricas en pantalla.
Mtl Lourdes Cahuich 21
Funciones virtuales
• Es normal empezar con una jerarquía pequeña de gráficas de objetos.
class Shape { /* ... */ };
class Circle: public Shape { /* ... */ };
class Rectangle: public Shape { /* ... */ };
Mtl Lourdes Cahuich 22
Funciones virtuales
• Supongamos que debemos tener la capacidad de mantener un registro de una colección de esa forma de objetos.
• Suponga que deseamos mantener un arreglo de formas de cualquier tipo.
• Podríamos intentar un arreglo del tipo Shape
Mtl Lourdes Cahuich 23
Funciones virtuales
• Esto es razonable, puesto que es legítimo hacer una asignación de una clase hija a una variable de la clase base.
Circle C(3); // radius 3
Shape S[10];
S[0] = C; // syntactically correct, but ...
Mtl Lourdes Cahuich 24
Funciones virtuales
• Desafortunadamente, las partes adicionales de la clase hija son simplemente "desnudadas" durante la tarea.
• Esto se conoce como el problema de las rebanadas o slicing problem.
• Perdemos a todos los miembros adicionales de los datos de la clase hija.
Mtl Lourdes Cahuich 25
Funciones virtuales
• El rebanar, sin embargo, no ocurre cuando tratamos con los apuntadores.
• Por lo tanto, podemos salvar nuestro proyecto usando un arreglo de apuntadores a las formas.
Mtl Lourdes Cahuich 26
Shape *layout[10];
layout[0] = new Circle(3);//radius 3
layout[1] = new Rectangle(2, 4);
// width 2, height 4
Mtl Lourdes Cahuich 27
Funciones virtuales
• En seguida, necesitamos la clase Circle y Rectangle para reemplazar el método heredado del area()para proporcionar los detalles específicos sobre como calcular sus áreas respectivas.
• Una vez hecho esto, podemos intentar lo siguiente.
Mtl Lourdes Cahuich 28
cout << layout[0]->area() << endl; // prints 0
cout << layout[1]->area() << endl;
// prints 0
Mtl Lourdes Cahuich 29
Funciones virtuales
• El problema es que el tipo estático de layout[0] es Shape* y, por lo tanto, el método area() que pertenece a la clase Shape se invoca, en lugar del método específico area() para cada uno de esos objetos del arreglo
Mtl Lourdes Cahuich 30
Funciones virtuales
• Lo que necesitamos es un mecanismo que revise el tipo dinámico de layout[0], por ejemplo, determina que es Circle*, y después llama al método del area() de la clase Circle.
• Esto se logra en C++ usando funciones virtuales
Mtl Lourdes Cahuich 31
• La redefinición apropiada de la clase Shape, particularmente su método area().
• El método area() en las clases hijas no necesita ser redefinido (aunque es bien visto asociar la palabra reservada virtual a esos métodos).
Mtl Lourdes Cahuich 32
class Shape {private: /* ... */public:
virtual float area(void) { return 0;}
/* ... */};
Mtl Lourdes Cahuich 33
Funciones virtuales
• Asumiendo que Circle y Rectangleprovean su propio método area()reemplazando el que está en Shape, obtenemos la salida correcta.
cout << layout[0]->area() << endl;
// prints 28.2743
cout << layout[1]->area() << endl;
// prints 8
Mtl Lourdes Cahuich 34
Funciones virtuales puras
• También pudimos modificar Shapehaciendo area()no sólo virtual sino también indefinida totalmente.
• Una función de este tipo es llamada una función virtual pura.
Mtl Lourdes Cahuich 35
class Shape {
private:
/* ... */
public:
virtual float area(void) = 0;
// totally undefined
/* ... */
};
Mtl Lourdes Cahuich 36
Clase abstracta
• Una clase que contiene una función virtual pura se conoce como clase abstracta. Implantaciones en C++ solamente usan clases abstractas en conjunto con herencia.
• En otras palabras, los programadores nunca crean instancias de clases abstractas.
Mtl Lourdes Cahuich 37
Clase abstracta
• Existen simplemente para especificar la interfaz común de las clases hijas y para tener acceso a estas clases hijas polimórficas.
• En resumen, para obtener un comportamiento polimórfico, necesitamos:– usar apuntadores en lugar de objetos directos debido al rebanado
– declarar funciones miembro virtuales