Herencia y polimorfismo

Documentos relacionados
Necesidad de la herencia pertenencia variedad is a has a herencia variedad definir una clase modificando una o más clases añadir nuevos miembros

Por ejemplo, considerando la jerarquía de herencia de Figuras Geométricas de la siguiente figura, es posible hacer uso del concepto de polimorfismo.

Tema 6. Gestión dinámica de memoria

Polimorfismo. Métodos virtuales

PROGRAMACION ORIENTADA A OBJETOS EN C++

Introducción. Herencia y Polimorfismo. Ejemplos (I) Ejemplos (II) Control de Acceso. Herencia

Definición y Conversión de datos. Agustín J. González ELO-329

Java Avanzado Facultad de Ingeniería. Escuela de computación.

Iteradores y contenedores en C++

Derechos de Acceso: COMPOSICION

Aplicaciones de Escritorio

Clases y Objetos en Java. ELO329: Diseño y Programación Orientados a Objetos

Tutorial de C# Delegados y Eventos. Por: Óscar López, M.Sc.

INSTITUTO TECNOLOGICO de la laguna Programación Orientada a Objetos en C++

Principios de Computadoras II

Métodos que devuelven valor Dado el siguiente triángulo rectángulo:

PROGRAMACIÓN EN C#.NET Programación Orientada a Objetos en C# Ing. Bruno López Takeyas

Tema: Clases y Objetos en C#. Parte II.

TEMA 8: Gestión dinámica de memoria

PRÁCTICA No 4 POO Encapsulación. El alumno conocerá los principios de la encapsulación, y el uso de constructores para la inicialización de datos

Conceptos a tratar. Fundamentos de la Programación Orientada a Objetos Ampliación sobre clases y objetos

El patrón Composite (Compuesto) Propósito Componer los objetos a una estructura de jerarquía de relación partetodo.

Clases en C++ Universidad de Carabobo Facultad Experimental de Ciencias y Tecnología Algoritmos y Programación II. Enero de 2005

Agradecimientos. Nota de los autores. 1 Problemas, algoritmos y programas 1

Test : Conteste exclusivamente en una HOJA DE LECTURA ÓPTICA, no olvidando marcar que su tipo de examen es A.

Programación Orientada a Objetos (POO)

PROYECTO FIGURAS DIAGRAMA DE FLUJO

Unidad Didáctica 2. Elementos básicos del lenguaje Java Tipos, declaraciones, expresiones y asignaciones

Estructuras de Datos y Algoritmos. Primeros ejemplos de TDA

Clases en C++ Agustín J. González ELO329

Herencia e Interfaces

Objeto Clase Atributo / Método Encapsulamiento Mensaje Herencia Polimorfismo Encadenamiento Dinámico

- Compilar y ejecutar programas en Java - Estructura básica de una clase - El comando javac - El comando java - Introducción al IDE de desarrollo

HERENCIA Y TIPOS. Articulo. Video Audio Altavoces. Amplificador

TECNICAS DE PROGRAMACION Universidad Católica Los Angeles de Chimbote METODOS CONSTRUCTORES Y LA REFERENCIA THIS

Tema 3: Herencia en C++ Programación Orientada a Objetos Curso 2008/2009 Begoña Moros Valle

Curso de Java POO: Programación orientada a objetos

Tema: Sobrecarga de Operadores.

Descripción y Contenido del Curso. Programación C++ Capacity Academy.

CONTENIDOS. La herencia permite: - Adoptar automáticamente características ya implementadas. Ahorro de tiempo y esfuerzo

La Herencia: Teoría (1)

UNIVERSIDAD AUTÓNOMA DE CHIAPAS LICENCIATURA EN SISTEMAS COMPUTACIONALES

Carlos Montenegro. Programación Orientada a Objetos Proyecto Curricular de Ingeniería de Sistemas

Introducción al lenguaje C

Programación orientada a objetos. Capítulo 8 Mejora de las estructuras mediante herencia

2.2 Nombres, Ligado y Ámbito

Computación Avanzada Clase 3. Mauricio Hidalgo Barrientos

Tipos algebraicos y abstractos. Algoritmos y Estructuras de Datos I. Tipos algebraicos

Tema 13: Apuntadores en C

Conceptos de Programación Orientada a Objetos

D é c i m o n o v e n a S e s i ó n. Metodologías y Técnicas de Programación II C++ Herencia III

Programación con Visual C#

Tema: Punteros a Objetos. Puntero this.

C# para no Programadores

Las plantillas permiten definir funciones genéricas.

RESUMEN DE CONCEPTOS BASICOS DE PROGRAMACION JAVA

Los constructores son funciones miembro especiales que sirven para inicializar un objeto de una determinada clase al mismo tiempo que se declara.

Modulo 11. Clases y Objetos en Java

Programación Orientada a Objetos con Java. Elementos Básicos del Lenguaje Java. Relación entre clases. Ejemplo de Clase: Punto !

Arrays. Programación. Licenciatura de Lingüística y Nuevas Tecnologías

Conceptos más avanzados de Programación Orientada a Objetos

Programación Orientada a Objetos

Introducción a C++ y Code::Blocks

Guía - Taller # 2 (JAVA)

CURSO DE LENGUAJE C. 4.1 Conceptos básicos de funciones 4.2 Funciones que regresan valores no enteros 4.3 Variables externas 4.4 Reglas de alcance

CURSO 2º GRUPO Junio 2011

Prácticas de Programación

Guía práctica de estudio 04: Clases y objetos

Prof. Dr. Paul Bustamante

Tema 5: Programación Orientada a Objetos en C++ Programación Orientada a Objetos Curso 2009/2010 Begoña Moros Valle

20483 Programación en C#

Tema 7: Polimorfismo. Índice

Tema 7. El sistema de clases

Diseño Basado en Componentes. Curso 2008 / 09

Tema 3. Programación orientada a objetos en Java (Parte 1)

16. Herencia Definición de herencia. 168 A. García-Beltrán y J.M. Arranz

Parte I: Elementos del lenguaje Ada

Programación 1 Tema 3. Información, datos, operaciones y expresiones

Variables. Una variable no es más que un nombre simbólico que identifica una dirección de memoria: vs.

Clases y Objetos. Informática II Ingeniería Electrónica

Tema: Herencia Simple y Múltiple en C++.

Programación orientada a objetos. Resumen de Temas Unidad 4: Sobrecarga

Unidad V Análisis Semántico. M.C. Juan Carlos Olivares Rojas

UNIVERSIDAD DE LOS ANDES NUCLEO UNIVERSITARIO RAFAEL RANGEL (NURR) DEPARTAMENTO DE FISICA Y MATEMATICA AREA COMPUTACION TRUJILLO EDO.

Tema: Clases y Objetos en C++. Parte II.

Python: Programación Orientada. JESSE PADILLA AGUDELO Ingeniero Electrónico

PRÁCTICA DE LABORATORIO 4 Programación Orientada a Objetos

1. Ejemplo de clase : La clase Cuenta 2. Uso de la clase Cuenta. 3. Métodos y objetos receptores de mensajes (Importante)

Tema: Tipos Abstractos de Datos (TAD s) en C++.

Herencia. Hay clases que comparten gran parte de sus características.

Lección 2: Creando una Aplicación en Java. 1. Estructura del archivo de una clase. 3. Definiendo clases fundamentos

Elabore el diagrama de clases en UML y la codificación de un programa para resolver los siguientes problemas:

MASTER PROFESIONAL C# 5 Y ASP.NET MVC 5

Introducción a Java LSUB. 30 de enero de 2013 GSYC

Programación Concurrente y de Tiempo Real Guión de Prácticas 3: Reutilización de Clases: Modelo de Herencia en Java

Categorías de métodos. Métodos constructores y destructores

La sintaxis básica para definir una clase es la que a continuación se muestra:

Métodos, clases, y objetos

Caracteres y Cadenas Conversión de Datos Funciones y procedimientos Archivos cabecera. Fundamentos de programación

Ejercicios propuestos de. Programación orientada a objetos. con C++ Cristina Cachero Pedro J. Ponce de León

Transcripción:

Herencia y polimorfismo Programación Orientada a Objeto Ing. Civil en Telecomunicaciones Herencia Hemos visto cómo crear nuestras propias clases Clase InfoAlumno para calcular las notas Supongamos ahora que el curso tiene alumnos de postgrado y de pregrado Alumnos de postgrado tienen que hacer un trabajo extra Solución: crear clase nueva que hereda métodos de la clase existente Herencia Concepto básico para programación orientada al objeto Una clase derivada hereda funciones y atributos de la clase superior ó base Establece una jerarquía de clases unida por relación es un tipo de Un tenedor es un tipo de cubierto Un camión, una bicicleta y un avión son tipos de medios de transporte Herencia Clase Postgrado hereda la parte pública de Base Funciones miembro Otras variables y Funciones miembro funciones miembro Clase Base() Clase Postgrado() Clase Base // Define la interfaz Base(); Base(std::istream&); std::string nombre() const; std::istream& leealumnos(std::istream&); double nota() const; private: // Define la implementacion std::istream& leecomun(std::istream&); std::string n; double examen1, examen2; std::vector<double> tareas; ; Clase Postgrado Nueva clase Postgrado hereda la interfaz pública de Base Tiene su propio constructor y y agrega variables y funciones miembro class Postgrado: public Base { // Define la interfaz Postgrado(); Postgrado(std::istream&); std::istream& leealumnos(std::istream&); double nota() const; private: // Define la implementacion double extra; // nota extra para postgrado ; 2015 Mario Medina C. 1

Clase Postgrado Clase derivada de clase Base Toda función pública miembro de Base también es función pública miembro de Postgrado Excepto constructores, destructor y operador de asignación Si se usa private Base, las funciones públicas de Base son funciones privadas de Postgrado Clase Postgrado puede definir sus propias funciones miembro redefinir funciones miembro definidas en Base Clase Postgrado Hereda la interfaz pública de Base, la que ahora forma parte de la interfaz pública de Postgrado Clase Postgrado no define una función miembro nombre() porque puede invocar a la función nombre() de la clase Base No hay acceso a la implementación de Base La clase Postgrado no tiene acceso a las notas, ya que son variables privadas de Base Datos protegidos (protected) Notas y función leecomun() de clase Base no son accesibles a Postgrado Redefinirlos como elementos protegidos (protected) Permite acceso a elementos por parte de funciones miembro de clases derivadas No permite acceso por parte de los usuarios de estas clases derivadas Tipos de acceso Acceso en clase base Especificador de acceso en clase derivada Acceso en clase derivada private: : private Inaccesible : private private: : private private: private: : public Inaccesible : public : public private: : protected Inaccesible : protected : protected Clase Base Clase Base // Define la interfaz Base(); Base(std::istream& in); std::string nombre() const; std::istream& leealumnos(std::istream& in); double nota() const; // Estas funciones y variables // son accesibles por clases derivadas std::istream& leecomun(std::istream& in); double examen1, examen2; std::vector<double> tareas; private: // Esta variable es privada std::string n; ; string Base::nombre() const { return n; double Base::nota() const { // Llama a funcion no-miembro return ::nota(examen1, examen2, tareas); istream& Base::leeComun(istream& in) { in >> n >> examen1 >> examen2; return in; istream& Base::leeAlumnos(istream& in) { leecomun(in); leenotas(in, tareas); return in; 2015 Mario Medina C. 2

Clase Postgrado es istream& Postgrado::leeAlumnos(istream& in) { leecomun(in); in >> extra; // lee nota extra leenotas(in, tareas); return in; double Postgrado::nota() const { return min(base::nota(), extra); Supondremos que el alumno de postgrado tiene como nota el mínimo entre su trabajo extra y la nota calculada sin este trabajo Error por llamada recursiva si escribimos min(nota(), extra) Para construir un objeto de clase Postgrado, Se reserva espacio para el objeto Se invoca al constructor correspondiente de la clase Base Se inicializan los miembros de la clase Base Se invoca al constructor de la clase Postgrado Se inicializan los miembros de la clase Postgrado Se ejecuta el cuerpo del constructor de la clase Postgrado es Ejemplo: clase base Circulo // por omision Base(): examen1(0), examen2(0) { // que recibe un istream Base(std::istream& is) { leealumnos(is); //... ; class Postgrado: public Base { // ambos constructores llaman a Base::Base() Postgrado(): extra(0) { Postgrado(std::istream& is) { leealumnos(is); ; #define PI 3.14159535 class Circulo { double radio; // Circulo(double r = 1.0) { radio = r; double calcula() { return PI*radio*radio; ; Ejemplo: clase derivada Cilindro class Cilindro : public Circulo { double largo; // Cilindro(double r = 1.0, double l = 1.0) : Circulo(r), largo(l) { double calcula() { return largo*circulo::calcula(); ; Ejemplo: clase derivada Cilindro Comentarios al código Clase Cilindro hereda funciones públicas y protegidas de la clase Circulo de Cilindro llama explícitamente al constructor de Circulo Compilador hace esto implícitamente Cilindro podría inicializar su variable radio Cálculo de área de Cilindro llama explícitamente a función calcula() de la clase base Circulo 2015 Mario Medina C. 3

Ejemplo: clase derivada Cilindro Ejemplo: clase derivada Cilindro Circulo circ_1, circ_2(2); Cilindro cil_1(3, 4); cout << Circ_1 = << circ_1.calcula() << endl; cout << Circ_2 = << circ_2.calcula() << endl; cout << Cil_1 << cil_1.calcula() << endl; // Asigna un cilindro a un circulo circ_1 = cil_1; cout << Circ_1 = << circ_1.calcula() << endl; return 0; Un objeto de una clase derivada puede ser asignado directamente a un objeto de la clase base En el ejemplo, se asigna un cilindro a un círculo Sólo los miembros públicos ó protegidos de la clase base del objeto son asignados Asignación inversa (clase base a clase derivada) requiere de un constructor Clases derivadas Clase Cilindro contiene la parte pública de Circulo Funciones miembro Otras variables y Funciones miembro funciones miembro Clase Circulo() Clase Cilindro() Polimorfismo El polimorfismo permite usar el mismo nombre de función para obtener una respuesta en los objetos de una clase base y otra en los objetos de una clase derivada Ejemplo: Función compara() bool compara(const Base& b1, const Base& b2) { return b1.nombre() < b2.nombre(); Polimorfismo compara(base& b1, Base& b2) Función compara() está definida para objetos Base Se puede aplicar esta función a objetos Postgrado? Objeto Postgrado no incluye función nombre() Objeto Postgrado incluye un Objeto Base! Este objeto base incluye una función nombre() Aplicar función compara() a objeto Postgrado aplica la función al objeto Base contenido en el objeto Postgrado nombre() Clase Base() compara(b1, p2) nombre() Otras variables y funciones miembro Clase Postgrado() 2015 Mario Medina C. 4

Polimorfismo Función compara() anterior recibe como argumentos referencias a objetos Base Postgrado p; Base b; compara(b, p); Función compara() recibe referencia al objeto Base contenido en el objeto Postgrado Función puede invocar a las funciones miembro de ese objeto Base Pero, no puede invocar a las funciones miembro de Postgrado que no están contenidas en Base Polimorfismo Problema ahora se presenta al pasar objetos como argumento y acceder a función nota() bool comparanotas(base b1, Base b2) { return b1.nota() < b2.nota(); Tipo de objetos conocidos en tiempo de compilación Postgrado p; Base b; compara(b, p); Llama a función Base::nota() de ambos objetos Función comparanotas() comparanotas(base& b1, Base& b2) Función compara notas en vez de nombres bool comparanotas(const Base& b1, const Base& b2) { return b1.nota() < b2.nota(); La función comparanotas() falla Invoca a función nota() de objetos Base Objeto Postgrado define su propia función nota(), que no es llamada Función nota() de Postgrado sobrecarga a función nota() de Base comparanotas(b1, p2) nota() Clase Base() nota() Otras variables nota() Clase Postgrado() Sobrecarga de funciones Funciones virtuales Una función de una clase derivada sobrecarga (overrides) una función de la clase base si ambas Tienen el mismo nombre Tienen el mismo tipo de argumentos Tienen el mismo número de argumentos Son (o no son) const Retornan el mismo tipo Excepción: pueden retornar punteros a sus respectivas clases virtual double nota() const; //... Se determina qué versión de nota() usar dependiendo del tipo de los objetos involucrados al tiempo de ejecución Función compara() aplicada a objetos Base y Postgrado invoca funciones Base::nota() y Postgrado::nota() 2015 Mario Medina C. 5

comparanotas(base& b1, Base& b2) Funciones virtuales comparanotas(b1, p2) virtual nota() Clase Base() virtual nota() Otras variables nota() Clase Postgrado() Una función virtual debe ser declarada como tal en la clase base puede estar definida en la clase base puede estar definida en las clases derivadas El compilador decide qué función invocar al momento de ejecutar el programa La calidad de virtual se hereda a las clases derivadas Enlace dinámico Clase Base Base b; Postgrado p; Base* p_b; Base& r; b.nota(); // Enlace estático a Base::nota() p.nota(); // Enlace estático a Postgrado::nota() p_b = &b; // Puntero apunta a objeto Base p_b->nota(); // Enlace dinámico, llama a Base::nota() r = b; // r es una referencia a objeto Base r.nota(); // Enlace dinámico, llama a Base::nota() p_b = &p; // Puntero apunta a objeto Postgrado p_b->nota(); // Enlace dinámico, llama a Postgrado::nota() r = p; // r es una referencia a objeto Postgrado r.nota(); // Enlace dinámico, llama a Postgrado::nota() // Define la interfaz Base(): examen1(0), examen2(0) { Base(std::istream& in) { leealumnos(in); std::string nombre() const; virtual std::istream& leealumnos(std::istream& in); virtual double nota() const; std::istream& leecomun(std::istream& in); double examen1, examen2; std::vector<double> tareas; private: // Define la implementacion std::string n; ; Clase Postgrado Usando la clase derivada class Postgrado: public Base { Postgrado() : extra(0) { Postgrado(std::istream& in) { leealumnos(in); // Estas funciones son virtuales por herencia double nota() const; std::istream& leealumnos(std::istream& in); private: double extra; ; // Funcion no-miembro bool compara(const Base&, const Base& in); Hemos creado la clase Postgrado como una versión de la clase Base Cómo usarlas para calcular las notas de los alumnos? Dos versiones del programa que calcula notas, una para cada tipo de alumnos Se muestran en las transparencias siguientes 2015 Mario Medina C. 6

Función main para Base (I) Función main para Base (II) vector<base> alumnos; Base alumno; string::size_type maxlen = 0; while(alumno.leealumnos(cin)) { maxlen = max(maxlen, alumno.nombre().size()); alumnos.push_back(alumno); // Ordena los alumnos sort(alumnos.begin(), alumnos.end(), compara); for(vector<base>::size_type i = 0; i!= alumnos.size(); ++i) { cout << alumnos[i].nombre() << string(maxlen + 1 alumnos[i].nombre().size(), ); try { double nota_final = alumnos[i].nota(); streamsize prec = cout.precision(); cout << fixed << setprecision(3) << nota_final << setprecision(prec) << endl; catch(domain_error e) { cout << e.what() << endl; return 0; Función main para Postgrado (I) Función main para Postgrado (II) vector<postgrado> alumnos; Postgrado alumno; string::size_type maxlen = 0; while(alumno.leealumnos(cin)) { maxlen = max(maxlen, alumno.nombre().size()); alumnos.push_back(alumno); // Ordena alumnos sort(alumnos.begin(), alumnos.end(), compara); for(vector<postgrado>::size_type i = 0; i!= alumnos.size(); ++i) { cout << alumnos[i].nombre() << string(maxlen + 1 alumnos[i].nombre().size(), ); try { double nota_final = alumnos[i].nota(); streamsize prec = cout.precision(); cout << fixed << setprecision(3) << nota_final << setprecision(prec) << endl; catch(domain_error e) { cout << e.what() << endl; return 0; Polimorfismo y enlace dinámico Polimorfismo y enlace dinámico Los 2 códigos anteriores usan enlace estático Los tipos de objetos son conocidos al tiempo de compilación Las funciones virtuales nombre() y notas() también son escogidas al tiempo de compilación Queremos tener una versión que maneja ambos casos a través de referencias a objetos En ese caso, es necesario usar referencias ó punteros a objetos Base en vez de objetos Reemplazar Base por Base* Pero, puntero Base* debe apuntar a algo vector<base*> alumnos; Base *alumno; while(alumno.leealumnos(cin)) { El puntero *alumno no apunta a nada! Necesario reservar memoria para objeto Pero, para un objeto Base o Postgrado? Supondremos archivo contiene B ó P 2015 Mario Medina C. 7

Función de comparación Necesitamos nueva función de comparación que compare 2 punteros a objetos Base Tiene que llamar a función compara() que compare lo apuntado por los punteros bool comparabaseptrs(const Base* pb1, const Base* pb2) { return compara(*pb1, *pb2); Función main (I) vector<base*> alumnos; Base* alumno; char ch; string::size_type maxlen = 0; while(cin >> ch) { if (ch = B ) alumno = new Base; else alumno = new Postgrado; alumno->leealumnos(cin); maxlen = max(maxlen, alumno->nombre().size()); alumnos.push_back(alumno); sort(alumnos.begin(), alumnos.end(),comparabaseptrs); Función main (II) Comentarios al código anterior for(vector<base*>::size_type i = 0; i!= alumnos.size(); ++i) { cout << alumnos[i]->nombre() << string(maxlen + 1 alumnos[i]->nombre().size(), ); try { double nota_final = alumnos[i]->nota(); streamsize prec = cout.precision(); cout << fixed << setprecision(3) << nota_final << setprecision(prec) << endl; catch(domain_error e) { cout << e.what() << endl; delete alumnos[i]; return 0; Código anterior supone que los datos de cada alumno tienen antepuesto B o P Se cambiaron los objetos por referencias a objetos Se solicitan objetos dinámicamente Se libera memoria de los objetos al final A través de un puntero a objeto Base Pero, qué pasa al destruir un objeto Postgrado? es virtuales Funciones virtuales Código mostrado libera sólo la memoria del objeto Base contenido en un objeto Postgrado debe ser virtual también virtual ~Base() const; //... ; Ahora delete llama al destructor correcto En el ejemplo, Base declara la función nota() como virtual y define una implementación Base::nota() Clase derivada Postgrado también define una implementación Postgrado::nota() Enlace dinámico decide cuál función invocar en tiempo de ejecución Es posible instanciar un objeto de clase Base 2015 Mario Medina C. 8

Clase abstracta Es una clase que sólo sirve como base para clases derivadas No es posible instanciar objetos de esta clase, sólo de sus clases derivadas Para hacer una clase abstracta, basta definir una función virtual igual a 0 Las clases derivadas se ven obligadas a definir la función No puede estar definida en la clase base Ejemplo: Clase abstracta Figura() // Clase abstracta Figura class Figura { // Interfaz // por omision Figura() { // Funcion de acceso string nombre() const { return n; // Funcion virtual abstracta // No se define en la clase base virtual double area() const = 0; string n; ; Clase derivada Triangulo() class Triangulo: public Figura { // Interfaz Triangulo() { // por omision n = "Triangulo"; Triangulo(double b, double h) { n = "Triangulo"; base = b; altura = h; double area() const { return base*altura/2.0; private: // Implementacion double base; double altura; ; Clase derivada Rectangulo() class Rectangulo: public Figura { // Interfaz Rectangulo() { // por omision n = "Rectangulo"; Rectangulo(double a, double b) { n = "Rectangulo"; ladoa = a; ladob = b; double area() const { return ladoa*ladob; // Implementacion double ladoa; double ladob; ; Clase derivada Cuadrado() class Cuadrado: public Rectangulo { // Implementacion Cuadrado() { // por omision n = "Cuadrado"; // que define un rectangulo de // lados iguales Cuadrado(double a): Rectangulo(a, a) { n = "Cuadrado"; // Clase Cuadrado hereda funcion area() de clase // base Rectangulo ; // Funcion de comparacion de figuras bool compara(figura& f1, Figura& f2) { return f1.area() < f2.area(); Herencia de funciones virtuales La calidad de virtual se hereda al siguiente nivel de clases derivadas Clase Base A Clase derivada B Clase derivada C virtual f1() f1() f1() Función f1() de B es virtual Función f1() de C es virtual Clase Base A Clase derivada B Clase derivada C virtual f1() f1() Si clase B no define función f1(), la función f1() de C no es virtual 2015 Mario Medina C. 9