Está en la página 1de 11

¿Qué es la Programación Orientada a Objetos?

La P.O.O. (también conocida como O.O.P., por sus siglas en inglés) es lo que se conoce
como un paradigma o modelo de programación. Esto significa que no es un lenguaje
específico, o una tecnología, sino una forma de programar, una manera de plantearse la
programación. No es la única (o necesariamente mejor o peor que otras), pero se ha
constituido en una de las formas de programar más populares e incluso muchos de los
lenguajes que usamos hoy día lo soportan o están diseñados bajo ese modelo (PHP, AS2,
AS3,…).

Lo que caracteriza a la POO es que intenta llevar al mundo del código lo mismo que
encontramos en El Mundo Real™. Cuando miramos a nuestro alrededor ¿qué vemos?
pues, cosas, objetos, pero podemos reconocer estos objetos porque cada objeto pertenece a
una clase, eso nos permite distinguir, por ejemplo, un perro de un auto (porque son de
clases diferentes) y también un TV de otro (porque, aunque sean iguales, cada uno es un
objeto distinto). Éste es el modelo que la POO intenta seguir para estructurar un sistema.

Es importante recalcar nuevamente que la POO no es un lenguaje de programación, es


una forma de enfrentarse a ella. Esto significa que la POO le servirá para desarrollar en
muchos de los lenguajes comunes de hoy en día (incluso en ASPuaj!) manteniendo un
mismo esquema mental. Incluso le permitirá enfrentar otros proyectos que no
necesariamente estén relacionados con escribir código…

Abstracción de datos

Una característica importante de cualquier lenguaje de programación es la capacidad de


crear tipos de datos definidos por el usuario. Aunque se pueden crear en C sus propios
tipos, utilizando las palabras reservadas typedef y struct, los tipos resultantes no se pueden
integrar fácilmente en el resto del programa. Además, en C, sólo se pueden definir los
tipos en términos de datos; es decir, las funciones utilizadas para manipular esos tipos no
son parte de la definición del tipo.

Una definición de un tipo que incluye datos y funciones y el modo para encapsular los
detalles, se conoce como tipo abstracto de dato. En C++ se implementa mediante el uso de
tipos de datos definidos por el usuario, llamados clases. clase = datos + funciones

Una diferencia importante entre C y C++, es que en C++ se pueden declarar funciones
dentro de una estructura (no se requiere declarar punteros a funciones). Las estructuras
pueden tener también especificadas regiones de acceso (medios en que se puede controlar
el acceso a los datos).

La abstracción de datos en C++ se obtiene con los tipos de datos estructura (struct) y
clase (class).
Objetos

En C++ un objeto es un elemento declarado de un tipo clase. Se conoce también como una
instancia de una clase.

Los objetos se pueden tratar como cualquier variable C. La principal diferencia es que se
puede llamar a cualquiera de las funciones que pertenecen a un objeto, esto es, se puede
enviar un mensaje a ella.
class rectangulo
{
int base,altura;
public:
void dimensiones(int,int);
int area();
};

void rectangulo::dimensiones(int b,int h)


{
base=b;
altura=h;
}
int rectangulo::area()
{
return base*altura;
}
void main()
{rectangulo r; //declarar el objeto
r.dimensiones(3,5); //definir el tamaño
cout<<"area "<<r.area();
}

COMUNICACIÓN ENTRE OBJETOS

Los objetos realizan acciones cuando ellos reciben mensajes. El mensaje es esencialmente
una orden que se envía a un objeto para indicarle que realice alguna acción. Esta técnica
de enviar mensajes a objetos se denomina paso de mensajes. Mensajes y métodos son dos
caras de la misma moneda. Los métodos son los procedimientos que se invocan cuando un
objeto recibe un mensaje. En terminología de programación tradicional, un mensaje es
una llamada a una función.

activación de un objeto

A los objetos solo se puede acceder a través de su interfaz pública. ¿Cómo se permite el
acceso a un objeto? Un objeto accede a otro objeto enviándole un mensaje.

MENSAJES
Un mensaje es una petición de un objeto a otro objeto al que le solicita ejecutar uno de sus
métodos. Por convenio, el objeto que envía la petición se denomina emisor y el objeto que
recibe la petición se denomina receptor.

Estructuralmente un mensaje consta de tres partes:

 Identidad del receptor.

 El método que ha de ejecutar.

 Información especial necesaria para realizar el método invocado ( argumentos o


parámetros requeridos )

Objeto Fecha “ Fecha sumar 3 meses “

receptor método parámetros

Cuando un objeto está inactivo y recibe un mensaje se hace activo. El mensaje enviado por
otros objetos tiene asociado un método que se activará cuando el receptor recibe dicho
mensaje. La petición no especifica cómo se realiza la operación. Tal información se oculta
siempre al emisor.

Estructura interna de los objetos

La estructura interna de un objeto consta de dos componentes básicos:

 Atributos

 Métodos ( operaciones o servicios )

Atributos

Los atributos describen el estado del objeto. Un atributo consta de dos partes, un nombre
de atributo y un valor de atributo.

Los objetos simples pueden constar de tipos primitivos, tales como enteros, caracteres,
boolen, etc. Los objetos complejos pueden constar de pilas, conjuntos, listas, arrays, etc, o
incluso de estructuras recursivas de alguno o todos de sus elementos.

Métodos

Los métodos ( operaciones o servicios ) describen el comportamiento asociado a un objeto.


La ejecución de un método puede conducir a cambiar el estado del objeto o dato local del
objeto.
Cada método tiene un nombre y un cuerpo que realiza la acción o comportamiento
asociado con el nombre del método. En un LPOO, el cuerpo de un método consta de un
bloque de código procedimental que ejecuta la acción requerida. Todos los métodos que
alteran o acceden a los datos de un objeto se definen dentro del objeto. No se pueden
modificar los datos ( atributos ) de otros objetos directamente, sino que se ha de llamar a
los métodos de dichos objetos para que los modifiquen.

Un método dentro de un objeto se activa por un mensaje que se envía por otro objeto al
objeto que contiene el método. Del mismo modo, se puede llamar a un método de un objeto
a través de otro método de ese mismo objeto.

Concepto de clase

Una clase es un tipo de dato que contiene uno o más elementos dato llamados miembros
dato, y cero, una o más funciones que manipulan esos datos (llamadas funciones
miembro). Una clase se puede definir con struct, union o class. La sintaxis de una clase es:
class nombre_clase
{
miembro1;
miembro2;
...
funcion_miembro1();
funcion_miembro2();
...
};

Una clase es sintácticamente igual a una estructura, con la única diferencia de que en el
tipo class todos los miembros son por defecto privados mientras que en el tipo struct son
por defecto públicos.

En C se utiliza el término variable estructura para referirse a una variable de tipo


estructura. En C++ no se utiliza el término variable de clase, sino instancia de la clase.

HERENCIA.

C++ soporta herencia permitiendo a una clase incorporar otra clase dentro de su
declaración. Antes de discutir los detalles y la teoría, comencemos por un ejemplo de
herencia. La siguiente clase, llamada vehiculo_rodante, define muy ampliamente a
vehículos que viajan en la carretera. Este almacena el numero de ruedas que un vehículo
tiene y el numero de pasajeros que puede llevar.

Tip: "Una clase base es heredada por una clase derivada"

class vehiculo_rodante {

int ruedas;
int pasajeros;
public:
void set_ruedas(int num) { ruedas = num;}
int get_ruedas() { return ruedas; }
void set_pasajeros(int num) { pasajeros = num; }
int get_pasajeros() { return pasajeros; }

};

Puede usar esta amplia definición de un vehículo rodante para ayudar a definir tipos
específicos de vehículos. Por ejemplo, el fragmento de código mostrado aqui podría usarse
para ser heredado por una clase llamada 'camion'.

class camion : public vehiculo_rodante {


int carga;

public:
void set_carga(int size) { carga = size; }
int get_carga() { return carga; }
void mostrar();

};

Como 'camion' hereda de 'vehiculo_rodante', 'camion' incluye todo de 'vehiculo_rodante'.


Entonces agrega 'carga' a la misma, en conjunto con las funciones miembros que trabajen
sobre este dato.

Nótese como 'vehiculo_rodante' es heredado. La forma general para la herencia se


muestra aquí:

class clase_derivada : acceso clase_base {


cuerpo de la nueva clase
}

Aquí, acceso es opcional. Sin embargo, si se encuentra presente, debe ser public, private, o
protected. Aprenderá más sobre estas opciones más tarde, por ahora para todas las clases
heredadas usaremos public. Usar public significa que todos los miembros públicos de la
clase base serán también miembros públicos de la clase derivada. Por tanto, en el ejemplo
anterior, miembros de la clase 'camion' tienen acceso a los miembros públicos de
'vehiculo_rodante', justo como si ellos hubieran sido declarados dentro de 'camion'. Sin
embargo, 'camion' no tiene acceso a los miembros privados de 'vehiculo_rodante'. Por
ejemplo, 'camion' no tiene acceso a ruedas.

He aquí un programa que usa herencia para crear dos subclases de 'vehiculo_rodante'.
Una es 'camion' y la otra es 'automovil'.

// Demostrando la herencia.
#include <iostream>
using namespace std;

// Definir una clase base para vehiculos


class vehiculo_rodante {

int ruedas;
int pasajeros;

public:
void set_ruedas(int num) { ruedas = num;}
int get_ruedas() { return ruedas; }
void set_pasajeros(int num) { pasajeros = num; }
int get_pasajeros() { return pasajeros; }

};

// Definir un camion.
class camion : public vehiculo_rodante {

int carga;

public:
void set_carga(int size) { carga = size; }
int get_carga() { return carga; }
void mostrar();

};

enum tipo {carro, van, camioneta};

// Definir un automovil.
class automovil : public vehiculo_rodante {
enum tipo tipo_de_carro;

public:
void set_tipo(tipo t) { tipo_de_carro = t; }
enum tipo get_tipo() { return tipo_de_carro; };
void mostrar();

};

void camion::mostrar()
{
cout << "ruedas: " << get_ruedas() << "\n";
cout << "pasajeros: " << get_pasajeros() << "\n";
cout << "Capacidad de carga en pies cúbicos: " << carga << "\n";
}

void automovil::mostrar()
{
cout << "ruedas: " << get_ruedas() << "\n";
cout << "pasajeros: " << get_pasajeros() << "\n";
cout << "tipo: ";

switch(get_tipo()) {

case van:
cout << "van\n";
break;

case carro:
cout << "carro\n";
break;

case camioneta:
cout << "camioneta\n";

}
}

int main()
{
camion t1, t2;
automovil c;

t1.set_ruedas(18);
t1.set_pasajeros(2);
t1.set_carga(3200);

t2.set_ruedas(6);
t2.set_pasajeros(3);
t2.set_carga(1200);

t1.mostrar();
cout << "\n";
t2.mostrar();
cout << "\n";

c.set_ruedas(4);
c.set_pasajeros(6);
c.set_tipo(van);

c.mostrar();
return 0;
}

La salida de este programa se muestra a continuación:

ruedas: 18
pasajeros: 2
Capacidad de carga en pies cúbicos: 3200

ruedas: 6
pasajeros: 3
Capacidad de carga en pies cúbicos: 1200

ruedas: 4
pasajeros: 6
tipo: van

Polimorfismo
En C++ es posible declarar dos funciones diferentes que tengan el mismo nombre. Las
funciones deben diferir en la lista de argumentos, bien en el número de variables que se
pasan a la función, bien en el tipo de argumentos que recibe. Así, por ejemplo, se puede
definir una función que trabaje, bien con enteros, bien con strings; sólo hay que definir dos
funciones separadas con el mismo nombre:

#include <iostream.h>

void show(int val)


{
cout <<" Es un entero :"<< val << '\n';
}

void show(char *val)


{
cout <<"Es un carácter: "<< val << '\n';
}

main()
{
show (42);
show ("A");
show (452.2);
}
En la primera llamada a la función show, se le pasa un entero, por tanto se llama a la
primera copia de la función show. La segunda vez, el argumento es un carácter, por tanto
se utiliza la segunda definición, aquella que utiliza un carácter. Ahora bien, la tercera
llamada utiliza un número real, y no existe una definición de la función para este caso. El
compilador utiliza la primer definición. La salida del programa es:

Es un entero :42
Es un carácter: A
Es un entero :452

También podríamos haber convertido la variable con la que llamamos a la función a uno
de los tipos para los cual show está definida. Por ejemplo, si sustituimos la tercera
llamada del programa anterior por:

show ((int)452.2);

la salida será:

Es un entero: 42
Es un carácter: A
Es un entero : 452

Es interesante destacar que la forma en que el compilador de C++ implementa la


sobrecarga de funciones es bastante simple. Aunque las funciones compartan el mismo
nombre en el texto fuente, el compilador usa nombres diferentes. La conversión de un
nombre en el fichero fuente al nombre usado internamente se llama 'name mangling'. Por
ejemplo, el compilado de C++ convertirá el nombre void show(int) al nombre interno
VshowI, mientras que una función análoga con un argumento char* será llamada
VshowCP . Los nombres reales utilizados internamente dependen del compilador y no son
relevantes para el programador.

Algunos comentarios sobre la sobrecarga de funciones:

 El uso de más de una función con el mismo nombre pero acciones diferentes debe
ser evitado. En el ejemplo anterior, las funciones show() están relacionadas:
imprimen información en la pantalla.
 C++ no permite que varias funciones difieran sólo en su valor devuelto. Dos
funciones de este tipo no podrín ser distinguidas por el compilador.
 La sobrecarga de funciones puede conducir a sorpresas. Supongamos una
sentencia como:

show (0);

dadas las funciones anteriores show() anteriores. El cero puede ser interpretado
como un puntero NULL a un carácter o como un entero con el valor 0. C++
elegirá llamar a la función que espera un argumento entero, que puede no ser lo
que se esperaba.

CLASES

La clase es la construcción del lenguaje utilizada más frecuentemente para definir los tipos
abstractos de datos en lenguajes de programación orientados a objetos. Generalmente,
una clase se puede definir como una descripción abstracta de un grupo de objetos, cada
uno de los cuales se diferencia por un estado específico y es capaz de realizar una serie de
operaciones.

En programación, una clase es una estructura que contiene datos y procedimientos ( o


funciones) que son capaces de operar sobre esos datos. Dentro de un programa, las clases
tienen dos propósitos principales: definir abstracciones y favorecer la modularidad.

A partir de una clase se puede definir un número de objetos. Cada uno de estos objetos
tendrá, generalmente, una serie de características propias, aunque compartirán
operaciones comunes. Los objetos ocupan espacio en memoria, y en consecuencia deberán
crearse o instanciarse, así como destruirse para liberar el espacio ocupado. Dos
operaciones comunes típicas en cualquier clase son:

 Constructor: una operación que crea un objeto y/o inicia su estado.

 Destructor: una operación que libera el estado de un objeto y/o destruye el propio
objeto.

Cuando se desea crear una nueva instancia de una clase, se llama a un método de la
propia clase para realizar el proceso de construcción. Los métodos constructores se
definen como métodos de la clase. De modo similar, los métodos empleados para destruir
los objetos y liberar la memoria ocupada también se definen dentro de la clase.

3.1 CLASES ABSTRACTAS

Con frecuencia, cuando se diseña un modelo orientado a objetos es útil introducir clases a
cierto nivel que pueden no existir en la realidad pero que son construcciones conceptuales
útiles. Estas clases se conocen como clases abstractas.

Una clase abstracta normalmente ocupa una posición adecuada en la jerarquía de clases
que le permite actuar como un depósito de métodos y atributos compartidos para las
subclases de nivel inmediatamente inferior.

Las clases abstractas no tienen instancias directamente. Se utilizan para agrupar otras
clases y capturar información que es común al grupo. Sin embargo, las subclases de clases
abstractas que corresponden a objetos del mundo real si pueden tener instancias.

Una clase abstracta podría ser una impresora:


+ inyectores + agujas

Las clases derivadas de una clase base o abstracta se conocen como clases concretas, que
ya pueden instanciarse (es decir, pueden tener instancias).

También podría gustarte