Programacion Orientada a Objetos
CLASES ABSTRACTAS
Estas
clases se caracterizan por tener algunos de sus métodos declarados como
abstractos, pero ¿qué es un método abstracto?. Un método abstracto es aquel que
está definido, pero no tiene cuerpo, es decir, le declaramos el nombre, los
parámetros y el tipo de devolución pero no le declaramos lo que va entre llaves
"{}", es más, no le ponemos llaves.
Estas
clases se utilizan para permitir que otras clases hereden de ella y
proporcionar un modelo a seguir.
La
declaración de una clase y método abstracto es el siguiente:
Public
abstract class nombreClase{
public
abstract tipo nombre(argumentos (si los lleva));
}
Reglas
básicas de este tipo de clases:
Como
ya he mencionado, una clase se declara abstracta si tiene algún método
abstracto.
Una
clase abstracta no puede crear objetos, es decir, no podemos utilizar
"new" para una clase abstracta, ya que tiene métodos que no están
definidos.
Una
clase abstracta no puede ser a la vez "final".
Si
una clase hereda de una clase abstracta, deberá de sobreescribir todos los
métodos abstractos, si no es así, la clase que hereda deberá ser pasada a
abstracta.
Una
clase abstracta puede llevar métodos NO abstractos, pero solo con que exista un
método abstracto, la clase deberá ser pasada a abstracta.
Como
los métodos estáticos no pueden ser redefinidos, un método abstracto no puede
ser estático.
Una
clase abstracta si puede tener constructores. Como sabemos, no es posible crear
objetos de una clase abstracta, pero de una clase, la cual herede de una clase
abstracta, si se pueden crear objetos, y como sabemos cuando creamos un objeto
de una clase que hereda, la primera llamada de su constructor es una llamada al
constructor de la clase "padre", lo que permite que aunque no cree un
objeto, si se pueda utilizar su constructor.
Este
Tipo de Clases nos permiten crear “método generales”, que recrean un
comportamiento común, pero sin especificar cómo lo hacen. A nivel de código tienen por particularidad que algunos
de sus métodos no tienen “cuerpo de declaración”, ¿qué quiere decir esto? no
tienen las llaves { } ni código dentro de ellos y deben estar precedidos por la
palabra clave abstract. Si una clases contiene uno o más métodos abstractos
está clase debe ser abstracta. Estas clases como son generalidades no pueden
ser instanciadas por ningún objeto (se dice que su nivel de abstracción es
demasiado alto), entonces su único fin es ser heredado/extendido por otras
clases.
Ejemplo
public abstract class
Figura {
// Atributos:
public int numeroLados;
public int area;
public int volumen;
// Métodos:
abstract public void calcularArea();
abstract public void calcularVolumen();
}
En
este poco original ejemplo se puede apreciar que toda figura tiene un método
para calcular su Área y Volumen.
Pongamos un ejemplo:
Bien,
en esta clase abstracta tenemos:
Un
atributo de tipo "String" llamado "color".
Un
constructor al cual le pasamos un parámetro de tipo "String".
2
métodos abstractos.
Un
método NO abstracto
Creamos
una clase llamada cuadrado que herede de Figura la cual posee:
2
atributos "x" e "y".
Un
constructor al cual le pasamos 3 parámetros.
Una
llamada al constructor de la superclase "Figura", la cual, como le
pusimos un parámetro, a super() le tenemos que pasar un parámetro.
Los
2 métodos heredados, a los cuales les damos cuerpo.
Creamos
una clase Círculo que herede de figura, la cual posee lo siguiente:
Un
atributo.
Un
constructor con parámetros.
Una
llamada al constructor de la superclase "Figura" a la cual le pasamos
el parámetro correspondiente.
Los
2 métodos heredados de "Figura" con cuerpo.
Bien
en esta última clase realizamos un pequeño menú con los bucles
"SWITCH" y "DO/WHILE".
Comenzamos
introduciendo una opción, por ejemplo 1.
El
switch nos manda a la opción "case 1". En ella se nos pide el radio y
el color del futuro Circulo.
Una
vez introducido los datos que nos pide, creamos un objeto de la clase Circulo,
al cual le pasamos los parámetros que
nos pide. Cabe mencionar, que como ya dijimos, no es posible crear un objeto de
la clase "Figura" ya que es una clase abstracta, pero con la ayuda
del polimorfismo podemos crear un objeto de la clase Circulo y así poder
utilizar atributos y métodos de la clase "Figura"
Figura
f=new Figura();// Esto nos da error
Figura
f=new Circulo();//Esto está bien.
Nos
imprime por pantalla el área, el perímetro y el color.
Tras
esto, nos vuelve aparecer el menú para crear otro objeto, o para salir de la
aplicación, en cuyo caso no volverá a aparecer el menú.
ASIGNACION DINAMICA DE MEMORIA
Es la asignación de almacenamiento de memoria para
utilización por parte de un programa de computador durante el tiempo de
ejecución de ese programa. Es una manera de distribuir la propiedad de recursos
de memoria limitada entre muchas piezas de código y datos. Un objeto asignado
dinámicamente permanece asignado hasta que es desasignado explícitamente, o por
el programador o por un recolector de basura; esto es notablemente diferente de
la asignación automática de memoria y de la asignación estática de memoria. Se
dice que tal objeto tiene tiempo de vida dinámico.
Otra de las grandes ventajas de la utilización de
punteros es la posibilidad de realizar una asiganación dinámica de memoria.
Esto significa que la reserva de memoria se realiza dinámicamente en tiempo de
ejecución, no siendo necesario entonces tener que especificar en la declaración
de variables la cantidad de memoria que se va a requerir. La reserva de memoria
dinámica añade una gran flexibilidad a
los programas porque permite al programador la posibilidad de reservar la
cantidad de memoria exacta en el preciso instante en el que se necesite, sin
tener que realizar una reserva por exceso en prevención a la que pueda llegar a
necesitar.
Dado que los
punteros se pueden aplicar a cualquier tipo de variable se puede entonces
realizar una asignación de memoria dinámica para cualquier variable. La función
malloc es la que se utiliza para realizar una reserva de memoria y se encuentra
en el archivo de cabecera <stdlib.h>.
La memoria dinámica es un espacio de almacenamiento que
se puede solicitar en tiempo de ejecución. Además de solicitar espacios de
almacenamiento, también podemos liberarlos (en tiempo de ejecución) cuando
dejemos de necesitarlos.
Para realizar esta administración de la memoria dinámica,
C++ cuenta con dos operadores new y delete. Antes de utilizarlos, debemos
incluir el encabezado <new>.
El operador new
reserva memoria dinámica de cualquier tipo, esto es:
tipos primitivos (int, double, etc)
tipos definidos por el usuario (clases o estructuras).
Veamos las siguientes líneas:
int *ptrEntero;
ptrEntero = new int;
/*(al puntero ptrEntero le asignamos
dinamicamente espacio para contener un valor int)*/
int
*ptrEnteroA;
ptrEnteroA
= new int(5);
/*(igual que al anterior
pero de paso lo inicializamos en 5)*/
También podríamos
hacerlo con un arreglo, para esto:
int *arreglo = new
int[45];
/*
(creamos un arreglo dinámico, ésta vez lo
hacemos en la misma línea en la que
declaramos el puntero)
*/
Supongamos ahora
que poseemos una clase Punto, podríamos crear objetos dinámicos a partir de
esta clase.
Punto *ptrQ;
ptrQ = new Punto(4,5);
/*
(en la segunda línea le pasamos
además dos parámetros separados por
coma al constructor de Punto)
*/
Hemos estado
pidiendo memoria dinámica, una vez utilizada lo correcto sería liberarla antes
de que finalice el programa para esto utilizaremos el operador delete:
delete ptrEntero;
delete ptrEnteroA;
delete ptrQ;
delete [] arreglo;
//Si no usaramos [] no se liberaría el arreglo entero
programa, con una
sencilla clase Punto, y la declaración de algunos objetos en la memoria
dinámica.
#include
<iostream>
using
std::cout;
using
std::endl;
#include <new> //para poder utilizar new y delete
class Punto
{
public:
Punto(int X=0,int
Y=0)
{
establecer(X,Y);
}
void
establecer(int x1,int y1)
{
x = x1;
y = y1;
}
void
imprimir(void)
{
cout << "(" <<
x << "," << y << ")" << endl;
}
private:
int x;
int y;
};
int main()
{
//declaracion e
inicializacion
Punto J(45,-12);
Punto *ptrQ;
ptrQ = new
Punto(5,7);
Punto
*arreglodePuntos;
arreglodePuntos =
new Punto[10];
//imprimimos
cout << "J";
J.imprimir();
cout << "ptrQ";
ptrQ->imprimir();
for (int i = 0 ; i < 10 ; i++)
{
cout <<
"arreglodePuntos[" << i <<"]";
arreglodePuntos[i].imprimir();
}
//liberamos
delete ptrQ;
delete []
arreglodePuntos;
//fin
return 0;
}
No hay comentarios:
Publicar un comentario