7. Heredando y ampliando la clase base
Curso: Introducción a C++, por Nacho Cabanes (antiguo)
7. Heredando y ampliando la clase base
Ahora podemos plantearnos mejorar esta clase de objetos para "pantalla de texto", y añadirle una serie de posibilidades extras, o modificar ligeramente su comportamiento actual.
Pues aquí entra en juego una de las posibilidades más interesantes de la Programación Orientada a Objetos: la reutilización. No necesitamos partir de cero, sino que podemos crear una clase que tome como base la que ya existe, "heredando" de ella todas sus características. Podremos redefinir las que no nos interesen, o añadir otras nuevas.
Por ejemplo, vamos a crear una clase "pantalla de texto" mejorada, que nos permita además escribir un texto centrado en cierta línea de la pantalla.
Igual que antes, crearemos un fichero de cabecera, otro de desarrollo y otro que pruebe el resultado.
El fichero de cabecera será:
1:
2: //
3: // pant04.h
4: //
5: // Introducción a C++
6: // Jose Ignacio Cabanes
7: //
8: // Cuarto ejemplo: Pantalla mejorada
9: // Versión para TC++ (MsDos)
10: //
11: /////////////////////////////////////////////
12:
13: #ifndef _PANT4_H
14: #define _PANT4_H
15:
16: #include "pant03.h"
17:
18: // ---------------------------------------------------------
19: // CLASE : PantallaTM
20: // Pantalla en modo texto, mejorada
21: // ---------------------------------------------------------
22: class PantallaTM: public PantallaTexto {
23: public:
24: void EscribeCent(
25: int Y, char *texto); // Escribe un mensaje centrado
26: };
27:
28: #endif
Sólo hay una novedad: la clase PantallaTM es un caso concreto de "pantalla de texto", un descendiente de ésta. Por eso la declaramos diciendo que proviene de PantallaTexto (el indicador de acceso "public" es para que los métodos y atributos sigan siendo como en la clase "padre": en nuestro caso concreto, los atributos eran y seguirán siendo privados, y los métodos eran y seguirán siendo públicos).
El fichero de desarrollo de la clase "PantallaTM" será
1: //
2: // pant04.cpp
3: //
4: // Introducción a C++
5: // Jose Ignacio Cabanes
6: //
7: // Cuarto ejemplo: Pantalla mejorada
8: // Versión para TC++ (MsDos)
9: //
10: /////////////////////////////////////////////
11:
12: #include <string.h>
13: #include "pant04.h"
14:
15: // ====================================================================
16: // A continuación viene el desarrollo de las funciones (métodos)
17:
18: // ----------------- PantallaTM -------------------------
19: // Escribe un mensaje centrado en una línea
20:
21: void
22: PantallaTM::EscribeCent( int Y, char *texto) {
23: Escribe( (LeerMaxX() - LeerMinX() - strlen(texto)) / 2, Y, texto);
24: }
Para acceder a los valores máximo y mínimo de las coordenadas X e Y, hemos empleado las funciones LeerMaxX() y similares, dado que no estamos en la clase original PantallaTexto, sino en una que desciende de ella, por lo que no podemos acceder directamente a los atributos. Esta es una de las formas de trabajar "altamente recomendadas" en Programación Orientada a Objetos: la ocultación de los detalles, para que los cambios que podamos hacer a los atributos de una clase no afecten a las clases que se deriven de ella.
Si quisiéramos acceder directamente a los atributos (no es nada recomendable, es preferible la opción anterior), no deberíamos haberlos declarado como "private", sino como "protected", como ya se comentó anteriormente, para que las clases que "heredan" de la primera puedan acceder a ellos:
class PantallaTexto {
protected:
char maxX, minX; // Coordenadas máxima y mínima (horizontal)
char maxY, minY; // Coordenadas máxima y mínima (vertical)
public:
PantallaTexto(); // Método constructor
// ...
con lo que el cuerpo del método EscribeCent quedaría
Escribe( maxX - minX - strlen(texto)) / 2, Y, texto);
El ejemplo que usa esta clase "PantallaTM" podría ser:
1: //
2: // usapantm.cpp
3: //
4: // Introducción a C++
5: // Jose Ignacio Cabanes
6: //
7: // Cuarto ejemplo: Pantalla mejorada
8: // Versión para TC++ (MsDos)
9: // (este fuente se debe usar con
10: // "pant03.cpp" y "pant04.cpp")
11: //
12: /////////////////////////////////////////////
13:
14: #include "pant04.h"
15:
16: // Programa sencillo de ejemplo
17:
18: int main() {
19: PantallaTM pant; // Objeto de la clase "PantallaTexto" mejorada
20:
21: pant.Borra();
22: pant.Escribe(30,14, "Hola");
23: pant.EscribeCent(11, "Centrado");
24: if (pant.LeerMaxX() > 40)
25: pant.Escribe(45,8, "Hola");
26: return 0;
27: }
Para compilarlo, nuevamente le indicamos al compilador el nombre de los ficheros fuente que debe combinar para crear el ejecutable:
bcc32 usapantm.cpp pant04.cpp pant03.cpp
En este caso, y al igual que ya hicimos con el ejemplo anterior, indicamos primero USAPANTM porque queremos que sea éste el fichero que dé nombre al ejecutable.
En la mayoría de compiladores, existe una posibilidad más cómoda que ésta de escribirle uno a uno los nombres de los fuentes implicados: podemos crear un "proyecto" e indicarle qué ficheros van a ser los necesarios para construirlo. Esto ayudará incluso a que el compilador sólo recompile los fuentes que realmente hayan cambiado, en vez de volver a crear todos, y así se gana en rapidez y comodidad.
Actualizado el: 15-05-2006 15:04