sábado, 18 de mayo de 2013

Página 10. Estructuras de datos en C++

Capítulo 2 Clases y objetos

INTRODUCCIÓN

La modularización de un programa utiliza la noción de tipo abstracto de dato (TAD) siempre que sea posible. Si el lenguaje de programación soporta los tipos que desea el usuario el conjunto de operaciones sobre cada tipo, se obtiene un nuevo tipo de dato denominado TAD.

Una clase es un tipo de dato que contiene código (métodos) y datos. Una clase permite encapsular todo el código y los datos necesarios para gestionar un tipo de específico de un elemento de programa, tal como una ventana en la pantalla, un dispositivo conectado a una computadora, una figura de un programa de dibujo o una tarea realizada por una computadora. 

  • 2.1. CLASES Y OBJETOS
Las tecnologías orientadas a objetos combinan la descripción de los elementos en un entorno de proceso de datos con las acciones ejecutadas por esos elementos. Las clases y los objetos como instancias o ejemplares de ellas, son los elementos clave sobre los que se articula la orientación a objetos.
  • 2.1.1. ¿Qué son los objetos?
En el mundo real, las personas identifican los objetos como cosas que pueden ser percibidas por los cinco sentidos. Los objetos tienen propiedades específicas, tales como posición, tamaño, color, forma, textura, etc., que definen su estado. Los objetos también tienen ciertos comportamientos que los hacen diferentes de otros objeto.
Booch, define un objeto como "algo que tiene un estado, un comportamiento y una identidad", supongamos una máquina de una fábrica. El estado de la máquina puede estar funcionando/parada ("on/off"), su potencia, velocidad máxima, velocidad actual, temperatura, etc. Su comportamiento puede incluir opciones para arrancar y parar la máquina, obtener su temperatura, activar o desactivar otras máquinas, condiciones de señal de error o cambiar la velocidad. su identidad se basa en el hecho de que cada instancia de una máquina es única, tal vez identificada por un número de serie. Las características que se elijen para enfatizar en el estado y el comportamiento se apoyarán en cómo un objeto máquina se utilizará en una aplicación. En un diseño de un programa orientado a objetos, se crea una abstracción (un modelo simplificado) de la máquina basado en las propiedades y comportamiento que son útiles en el tiempo.

Martin/Odell definen un objeto como "cualquier cosa, real, abstracta, en la que se almacenan datos y aquellos métodos (operaciones) que manipulan los datos".
Un mensaje es una instrucción que se envía a un objeto y que cuando se recibe ejecuta sus acciones. Un mensaje incluye un identificador que contiene la acción que ha de ejecutar el objeto junto con los datos que necesita el objeto para realizar su trabajo. Los mensajes, por consiguiente, forman una ventana del objeto al mundo exterior.

El usuario de un objeto se comunica con el objeto mediante su interfaz, un conjunto de operaciones definidas por la clase del objeto de modo que sean todas visibles al programa. Una interfaz se puede considerar como una vista simplificada de un objeto. Por ejemplo, un dispositivo electrónico tal como una máquina de fax tiene una interfaz de usuario bien definida, esa interfaz incluye el mecanismo de avance de papel, botones de marcado, receptor y el botón "enviar". El usuario no tiene que conocer cómo está construida la máquina internamente, el protocolo de comunicaciones u otros detalles.
  • 2.1.1. ¿Qué son clases?
En términos prácticos, una clase es un tipo definido por el usuario. Las clases son los bloques de construcción fundamentales de los programas orientados a objetos. Booch denomina a una clase como "un conjunto de objetos que comparten una estructura y comportamiento comunes".

Una clase contiene la especificación de los datos que describen un objeto junto con la descripción de las acciones que un objeto conoce cómo ha de ejecutar. Estas acciones se conocen como servicios o métodos. Una clase incluye también todos los datos necesarios para describir los objetos creados a partir de la clase. Esos datos se conocen como atributos, variables o variables de instancia. El término atributo se utiliza en análisis y diseño orientado a objetos y el término variable instancia se suele utilizar en programas orientados a objetos.
  • 2.2. DECLARACIÓN DE UNA CLASE
Antes de que un programa pueda crear objetos de cualquier clase, la clase debe ser declarada y los métodos definidos (implementados). La declaración de una clase significa dar a la misma un nombre, darle nombre a los elementos que almacenan sus datos y describir de los métodos que realizarán las acciones consideradas en los objetos.

Formato


NombreClase      

Nombre definido por el usuario que identifica a la clase (puede incluir letras, números y                                     subrayados como cualquier identificador).

lista_de_miembros

Datos y funciones miembros de la clase.

Las declaraciones  o especificaciones no son código de programa ejecutable. Se utilizan para asignar almacenamiento a los valores de los atributos usados por el programa y reconocer los métodos que utilizará el programa. En C++, los métodos se denominan funciones miembro, normalmente en la declaración sólo se escribe el prototipo de la función. Las declaraciones de las clases se sitúan en archivos .h (NombreClase.h) y la implementación de las funciones miembro en el archivo .cpp (Nombreclase.cpp).

-------------------------------------------------------------------------------------------------------------------------------------------------------------------
EJEMPLO 2.1. Definición de una clase llamada Punto que contiene las coordenadas x e y de un punto en un plano.

La declaración de la clase se guarda en el archivo Punto.h:


//archivo Punto.h
class Punto
{
private:
  int x, y;                           // coordenadas x,y
public:
    Punto (int x_, int y_)            // constructor
    {
      x = x_;
      y = y_;
    }
    Punto() {x = y = 0;}              // constructor sin argumentos
      int leerX() const;              // devuelve el valor de x

      int leerY() const;              // devuelve el valor de y
      void fijarX (int valorX);       // establece el valor de x
      void fijarY (int valorY);       // establece el valor de y
};


La definición de las funciones miembro se realiza en el archivo Punto.cpp:
#include "Punto.php"
int Punto::leerX() const
{
  return x;
}
int Punto::leerY() const
{
  return y;
}
void Punto::fijarX(int valorX)
{
  x =  valorX;
}
void Punto::fijarY(int valorY)
{
  y = valorY;
}


-------------------------------------------------------------------------------------------------------------------------------------------------------------------
  • 2.2.1. Objetos
Una vez que una clase ha sido definida, un programa puede contener una instancia de la clase, denominada un objeto de la clase. Un objeto se crea de forma estática, de igual forma que se define una variable. También de forma dinámica, con el operador new aplicado a un constructor de la clase. Por ejemplo, un objeto de la clase Punto inicializado a las coordenadas (2,1):

Punto p1(2, 1);               // objeto de forma estática
Punto* p2 = new Punto(2, 1);  // objeto creado dinámicamente

Formato para crear un objeto
  NombreClase varObj(argumentos_constructor);

Formato para crear un objeto dinámico
  NombreClase* ptrObj;
 ptrObj = new NombreClase(argumentos_constructor);

Toda clase tiene una o más funciones miembro denominadas constructores, para inicializar el objeto cuando es creado; tienen el mismo nombre que el de la clase, no tienen tipo de retorno y pueden estar sobrecargados.

El operador de acceso a un miembro del objeto, selector punto (.), selecciona un miembro individual de un objeto de la clase. Por ejemplo:

Punto P2,                                   // llama al constructor sin argumentos
p2.fijarX(10);
cout << " Coordenada x es " << p2.leerX();

El otro operador de acceso es el selector flecha (->), selecciona un miembro de un objeto desde un puntero a la clase. Por ejemplo:

Punto* p;
p = new Punto(2, -5);                      // crea objeto dinámico
cout << " Coordenada y es " << p -> leerY();

  • 2.2.2. Visibilidad de los miembros de la clase
Un principio fundamental en programación orientada a objetos es la ocultación de la información. Significa que determinados datos del interior de una clase no se puede acceder por funciones externas a la clase. El mecanismo principal para ocultar datos es ponerlos en una clase y hacerlos privados. A los datos o métodos privados sólo se puede acceder desde dentro de la clase. Por el contrario, los datos o métodos públicos son accesibles desde el interior de la clase (véase la Figura 2.1).
Para controlar el acceso a los miembros de la clase se utilizan tres diferentes especificadores de acceso: public, private y protected. Cada miembro de la clase está precedido del especificador de acceso que le corresponde.

Formato

class NombreClase
{
  private:
         declaraciones de miembros privados;
  protected:
         declaraciones de miembros protegidos;
}

Figura 2.1. Secciones pública y privada de una clase.

public;
      declaraciones de miembros públicos;
};

Por omisión, los miembros que aparecen a continuación de la llave de inicio de la clase, {, son privados. A los miembros que siguen a la etiqueta private sólo se puede acceder por funciones miembro de la misma clase. A los miembros protected sólo se puede acceder por funciones miembro de la misma clase y de las clases derivadas. A los miembros que siguen a la etiqueta public se puede acceder dentro y desde el exterior de la clase. Las secciones public, protected y private pueden aparecer en cualquier orden.

-------------------------------------------------------------------------------------------------------------------------------------------------------------------
EJEMPLO 2.2. Declaración de la clase Foto y Marco con miembros declarados con distinta visibilidad.
class Foto
{
private:
       int nt;
       char opd;
protected:
       string q;
public:
       Foto(string r)   // constructor
       {
         nt = 0;
         opd = 'S';
         q = r;
       }
       double mtd();
};

class Marco
{
private:
       double p;
       string t;
public:
       Marco();        // constructor
       void poner()
       {
         Foto* u = new Foto("Paloma");
         p = u ->mtd();
         t = "**" + u -> q + "**";
       }
};


-------------------------------------------------------------------------------------------------------------------------------------------------------------------
Tabla 2.1. Visibilidad, "x" indica que el acceso está permitido

Tipos de miembro
Miembro de la clase
Miembro de una clase derivada
Miembro de otra clase (externo)
Private
Protected
Public
X
X
X

X
X


X

Aunque las secciones púbicas, privadas y protegidas pueden aparecer en cualquier orden, los programadores suelen seguir ciertas reglas en el diseño que citamos a continuación, y que usted puede elegir la que considere más eficiente.

  1. Poner los miembros privados primero, debido a que contiene los atributos (datos).
  2. Se pone los miembros públicos primero debido a que los métodos y los constructores son la interfaz del usuario de la clase.
En realidad, tal vez el uso más importante de los especificadores de acceso es implementar la ocultación de la información. El principio de ocultación de la información indica que toda la interacción con un objeto se debe restringir a utilizar una interfaz bien definida que permite que los detalles de implementación de los objetos sean ignorados. Por consiguiente, los datos y métodos públicos forman la interfaz externa del objeto, mientras que los elementos privados  son los aspectos internos del objeto que no necesitan ser accesibles para usar el objeto.

El principio de encapsulamiento significa que las estructuras de datos internas utilizadas en la implementación  de una clase no pueden ser accesibles directamente al usuario de la clase.
  • 2.2.3. Funciones miembro de una clase

La declaración de una clase incluye la declaración o prototipo de las funciones miembros (métodos). Aunque la implementación se puede incluir dentro del cuerpo de la base (inline), normalmente se realiza en otro archivo (con extensión .cpp) que constituye la definición de la clase. La Figura 2.2 muestra la declaración de la clase Producto.


Figura 2.2. definición típica de una clase.

-------------------------------------------------------------------------------------------------------------------------------------------------------------------
EJEMPLO 2.3 La clase Relacional representa un número relacional. Por cada dato, numerador, denominador, se proporciona una función miembro que devuelve su valor y otra función para asignar numerado y denominador. Tiene un constructor que inicializa un objeto a 0/1.

En esta ocasión las funciones miembro se implementan directamente en el cuerpo de la clase.

// archivo Racional.h
class Racional
{
private:
 int numerador;
 int denominador;
public:
 Racional()
 {
  numerador = 0;
  denominador = 1;
 }

 int leerN() const
 {
  return numerador;
 }

 int leerD() const
 {
  return denominador;
 }

 void fijar(int n, int d)
 {
  numerador = n;
  denominador = d;
 }
};

  • 2.2.4. Funciones miembro de una clase
Las funciones miembro definidas dentro del cuerpo de la declaración de la clase se denominan definiciones de funciones en linea (inline). Para el caso de funciones más grandes, es preferible codificar sólo el prototipo de la función dentro del bloque de la clase y codificar la implementación de la función en el exterior. Esta forma permite al creador de una clase ocultar la implementación de la función al usuario de la clase proporcionando sólo el código fuente del archivo de cabecera, junto con u archivo de implementació de la clase precompilada. 

En el siguiente ejemplo, FijarEdad() de la clase Lince se declara pero no se define en la declaración de la clase: 
class Lince
{
public:
     void FijarEdad(int a);
private:
     int edad;
     string habitat;
};

La implementación de una función miembro externamente a la declaración de la clase, se hace en una definición de la función fuera de línea. Su nombre debe de ser precedido por el nombre de la clase y el signo de puntuación :: denominado operador de resolución de ámbito. El operador :: permite al compilador conocer que FijarEdad() pertenece a la clase Lince y es por consiguiente, diferente de una función global que pueda tener el mismo nombre o de una función que tenga ese nombre que pueda existir en otra clase. La siguiente función global, por ejemplo, puede coexistir dentro del mismo ámbito que Lince::FijarEdad():
// función global
void FijarEdad(int valx);
{
     //..
}
// función en el ámbito de Lince
void Lince::FijarEdad(int a)
{
     edad = a;
}
La decisión de elegir funciones en línea y fuera de línea es una cuestión de eficiencia en tiempo de ejecución. Una función en línea se ejecuta normalmente más rápida, y que el compilador inserta una copia <<fresca>> de la función en un programa en cada punto en que se llama a la función. La definición de una función miembro en línea no garantiza que el compilador lo haga realmente en línea; es una decisión que el compilador toma, basado en los tipos de las sentencias dentro de la función y cada compilador de C++ toma esta decisión de modo diferente.

Si una función se compila en línea, se ahorrar el tiempo de la UCP (CPU) al no tener que ejecutar una instrucción "call" (llamar) para bifurcar a la función y no tener que ejecutar una instrucción return para retornar al programa llamador. Si una función es corta y se llama cientos de veces, se puede apreciar un incremento en eficiencia cuando actúa como función en línea.

Una función localizada fuera del bloque de la definición de una clase se puede beneficiar de las ventajas de las funciones en línea si está precedida por la palabra reservada inline:


inline void Lince::FijarEdad(int a)
{
     edad = a;
}


Dependiendo de la implementación de su compilador, las funciones que utilizan la palabra reservada inline se puede situar en el mismo archivo de cabecera que la definición de la clase.Las funciones que no utilizan inline se sitúan en el mismo módulo del programa, pero el archivo de cabecera. Estas funciones se sitúan en un archivo .cpp.


-------------------------------------------------------------------------------------------------------------------------------------------------------------------
Ejercicio 2.1

Definir una clase DiaAnyo con los atributos mes y día, los métodos igual() y visualizar(). El mes se registra como un valor entero (1, Enero, 2, Febrero, etc.). El día del mes se registra en otra variable entera día. escribir un programa que compruebe si una fecha es su cumpleaños.

La función principal, main(), crea un objeto DiaAnyo y llama al método igual() para determinar si coincide la fecha del objeto con la fecha de su cumpleaños, que se ha leído de dispositivo de entrada.
// archivo DiaAnyo.h

class DiaAnyo
{
private:
     int dia, mes;
public:
     DiaAnyo(int d, int m);
     bool igual(const DiaAnyo& d) const;
     void visualizar() const;
};

La implementación de las funciones miembro se guarda en el archivo DiaAnyo.cpp:

#include 
using namespace std;
#include "DiaAnyo.h"

DiaAnyo::DiaAnyo(int d, int m)
{
     dia = d;
     mes = m;
}

bool DiaAnyo::igual(const DiaAnyo& d) const
{
     if ((dia == d.dia) && (mes == d.mes))
          return true;
     else
          return false;
}

void DiaAnyo::visualizar() const
{
     cout << "mes =" << mes << " , dia = " << dia << endl;
}

Por último el archivo DemoFecha.cpp contiene la función main(), crea los objetos y se envian mensajes.
#include 
using namespace std;
#include "DiaAnyo.h"

int main()
{
     DiaAnyo* hoy;
     DiaAnyo* cumpleAnyos;
     int d, m;
     
     cout << "Introduzca fecha de hoy, día: ";
     cin >> d;
     cout << "Introduzca el número de mes: ";
     cin >> m;
     hoy = new DiaAnyo(d, m);
     cout << "Introduzca su fecha de nacimiento,día: ";
     cin >> d;
     cout << "Introduzca el número de mes: ";
     cin >> m;
     cumpleanyos =  new DiaAnyo(d, m);
     cout << "La fecha de hoy es ";
     hoy -> visualizar();
     cout << "Su fecha de nacimiento es ";
     cumpleanyos -> visualizar();
     if (hoy -> igual(*cumpleanyos))
          cout << "¡Feliz cumpleaños!" << endl;
     else
          cout << "¡Feliz día!" << endl;
     return 0;
}






















lunes, 6 de mayo de 2013

Página 9. Estructuras de Datos en C++



  • 1.8. PROGRAMACIÓN ORIENTADA A OBJETOS (POO)
La programación orientada a objetos, tal vez el paradigma de programación más utilizado en el mundo del desarrollo de software y de la ingeniería del software del siglo XXI, trae un nuevo enfoque a los retos que se plantean en la programación estructurada cuando los problemas a resolver son complejos. Al contrario de la programación procedimental que enfatiza en los algoritmos. la POO enfatiza en los datos. En lugar de intentar ajustar un problema al enfoque procedimental de un lenguaje, POO intenta ajustar el lenguaje al problema. La idea es diseñar formados de datos que correspondan con las características esenciales de un problema.

La idea fundamental de los lenguajes orientados a objetos es combinar en una única unidad o módulos, tanto los datos como las funciones que operan sobre esos datos. Tal unidad se llama objeto.

Las funciones de un objeto se llaman funciones miembro en C++ o métodos (este es el caso de SmallTalk, uno de los primeros lenguajes orientados a objetos) y son el único medio para ascender a sus datos. Los datos de un objeto, se conocen también como atributos o variables de instancia. Si se desea leer datos de un objeto, se llama una función miembro del objeto. Se accede a los datos y se devuelve un valor. No se puede acceder a los datos directamente. Los datos están ocultos, de modo que están protegidos de alteraciones accidentales. Los datos y las funciones se dice que están encapsulados un una única entidad. El encapsulamiento de datos y la  ocultación de los datos son términos clave en la descripción de lenguajes orientados a objetos.

Si se desea modificar losa datos de un objeto, se conoce exactamente cuáles son las funciones que interactuan con las funciones miembro del objeto: Ninguna otra función puede acceder a los datos. Esto simplifica la escritura, depuración y mantenimiento del programa. Un programa C++ se compone, normalmente, de un número de objetos que se comunican unos con otros mediante la llamada a otras funciones miembro. La organización de un programa en C++ se muestra en la Figura 1.5. La llamada a una función miembro de un objeto se denomina enviar un mensaje a otro objeto.

Figura 1.5. Organización típica de un programa orientado a objetos.


En el paradigma orientado a objetos, el programa se organiza como un conjunto finito de objetos que contiene datos y operaciones (funciones miembro en C++) que llaman a esos datos y que se comunican entre sí mediante mensajes.


  • 1.8.1. Propiedades fundamentales de la orientación a objetos.
Existen diferentes características ligadas a la orientación a objetos. Todas las propiedades que se suelen considerar, no son exclusivas de este paradigma, ya que pueden existir en otros paradigmas, pero en su conjunto definen claramente los lenguajes orientados a objetos. Estas propiedades son: 

  • Abstracción (tipos abstractos de datos y clases).
  • Encapsulado o encapsulamiento de datos.
  • Ocultación de datos.
  • Herencia.
  • Polimorfismo.
C++ soporta todas las características anteriores que definen la orientación a objetos, aunque hay numerosas discusiones en torno a la consideración de C++ como lenguaje orientado a objetos. La razón es que, en contraste con lenguajes tales como  Smalltalk, Java o C#, C++  no es un lenguaje orientado a objetos puro. C++ soporta orientación a objetos pero es compatible con C y permite que programas C++ se escriban sin utilizar características orientada a objetos. De hecho, C++ es un lenguaje multiparadigma que permite programación estructurada, procedimental, orientada objetos y genérica.

  • 1.8.2. Abstracción
La abstracción es la propiedad de los objetos que consiste en tener en cuenta sólo los aspectos más importantes desde un punto de vista determinado y no tener en cuenta los restantes aspectos. El término Abstracción, que se suele utilizar en programación, se refiere al hecho de diferenciar entre las propiedades externas de una entidad y los detalles de la composición interna de dicha entidad. Es la abstracción la propiedad que permite ignorar los detalles de un dispositivo complejo tal como la computadora, un automóvil, una lavadora o un horno de microondas, etc., y usarlo como una única entidad comprensible. Mediante la abstracción se diseñan y fabrican estos sistemas complejos en primer lugar y, posteriormente, los componentes más pequeños de los cuales están compuestos. Cada componente representa un nivel de abstracción en el cual el uso del componente se aísla de los detalles de la composición interna del componente. La abstracción posee diversos grados denominados niveles de abstracción.
En consecuencia, la abstracción posee diversos grados de complejidad que se denominan niveles de abstracción que ayudan a estructurar la complejidad intrínseca que posee los sistemas del mundo real. En el modelado orientado a objetos de un sistema esto significa centrarse en qué es y qué hace un objeto y no en cómo debe implementarse. Durante el proceso de abstracción es cuando se decide que características y comportamiento debe de tener el modelo.

Aplicando la abstracción se es capaz de construir, analizar y gestionar sistemas de computadoras complejos y grandes que no se podrían diseñar si se tratara de modelar a un nivel detallado. En cada nivel de abstracción se visualiza el sistema en términos de componentes, denominadas herramientas abstractas, cuya composición interna se ignora.

Esto nos permite concentrarnos en cómo cada componente interactúa con otros componentes y centrarnos en la parte del sistema que es más relevante para la tarea a realizar en lugar de perderse a nivel de detalles menos significativos.

En estructuras o registros, las propiedades individuales de los objetos se pueden almacenar en los miembros. Para los objetos es de interés cómo están organizados sino también qué se puede hacer con ellos. Es decir, las operaciones que forman la composición interna de un objeto son también importantes. El primer concepto en el mundo de la orientación nació con los tipos abstractos de datos (TAD). Un tipo abstracto de datos describe no sólo los atributos de un objeto, sino también su comportamiento (las operaciones). Esto puede incluir también una descripción de los estados que puede alcanzar un objeto.

Un medio de reducir la complejidad es la abstracción. Las características y los procesos se reducen a las propiedades esenciales, son resumidas o combinadas entre sí. De este modo, las características complejas se hacen más manejables.

-------------------------------------------------------------------------------------------------------------------------------------------------------------------
EJEMPLO 1.7. Diferentes modelos de abstracción del término coche (carro) .

  • Un coche (carro) es la combinación (o composición) de diferentes partes, tales como motor, carrocería, cuatro ruedas, cinco puertas, etc.
  • Un coche (carro) es un concepto común para diferentes tipos de coches. Pueden clasificarse por el nombre del fabricante (Audi, BMW, Seat, Toyota, Chrisler...), por su categoría (turismo, deportivo, todoterreno...) por el carburante que utilizan (gsaolina, gasoil, híbrido...)
La abstracción coche se utilizara siempre que la marca, la categoría o el carburante no sean significativos. Así un carro (coche) se utilizará para transportar personas o ir de Carche - lejos a Cazorla.

-------------------------------------------------------------------------------------------------------------------------------------------------------------------

  • 1.8.3. Encapsulamiento y ocultación de datos

El encapsulado o encapsulamiento de datos es el proceso de agrupar datos y operaciones relacionadas con la misma unidad de programación. En el caso de los objetos que poseen las mismas características y comportamiento se agrupan en clases, que no son más que unidades o módulos de programación que encapsulan datos y operaciones.
La ocultación de datos permite separar el aspecto de un componente, definido por su interfaz con el exterior, de sus detalles internos de implementación. Los términos ocultación de la información (information hiding) y encapsulamiento de datos (data encapsulation) se suelen utilizar como sinónimos, pero no siempre es así, a veces se utilizan en contextos diferentes. En C++ no es lo mismo, los datos internos están protegidos del exterior y no se pueden acceder a ellos más que desde su propio interior y, por tanto, no están ocultos. El acceso al objeto está restringido sólo a través de una interfaz bien definida.

El diseño de un programa orientado a objetos contiene, al menos, los siguientes pasos:
  1. Identificar los objetos del sistema.
  2. Agrupar en clases todo los objetos que tengan características y comportamientos comunes.
  3. Identificar los datos y operaciones de cada una de las clases.
  4. Identificar las relaciones que pueden existir entre las clases. 
En C++, un objeto es un elemento ideal con su propia identidad; por ejemplo, un libro, un automóvil... Una clase puede describir las propiedades genéricas de un ejecutivo de una empresa (nombre, titulo, salario, cargo...) mientras que un objeto representará a un ejecutivo específico (Luis Mackoy, director general). En general una clase define qué datos se utilizan para representar un objeto y las propiedades que se pueden ejecutar sobre esos datos.

Una clase describe un conjunto de objetos. En el sentido estricto de programación, una clase es un tipo de datos. Diferentes variables se pueden crear de este tipo. En programación orientada a objetos, éstas se llaman instancias. Las instancias son, por consiguiente, la realización de los objetos descritos en una clase. Estas instancias constan de datos o atributos descritos en la clase y se pueden manipular con las operaciones definidas dentro de ellas.

Los términos objeto e instancia se utilizan frecuentemente como sinónimos (especialmente en C++). Si una variable de tipo carro se declara, se crea un objeto carro (una instancia de la clase carro).

Las operaciones definidas en los objetos se llaman métodos. Cada operación llamada por un objeto se interpreta como un mensaje al objeto, que utiliza un método específico para procesar la información.

En el diseño de programas orientados a objetos se realiza en primer lugar el diseño de las clases que representan con precisión aquellas cosas que trata el programa. Por ejemplo, un programa de dibujo, puede definir clases que representan rectángulos, líneas pinceles, colores, etcétera. Las definiciones de clase, incluyen una descripción de operaciones permisibles para cada clase, tales como desplazamiento de un círculo o rotación de una línea. A continuación se prosigue el diseño de un programa utilizando objetos de la clases.

El diseño de las clases fiables y útiles pueden ser una tarea difícil. Afortunadamente, los lenguajes POO facilitan la tarea ya que incorporan clases existentes en su propia programación. Los fabricantes de software proporcionan numerosas bibliotecas de clases, incluyendo bibliotecas de clases diseñadas para simplificar la creación de programas para entornos tales como Widows, Linux, Macintosh, Unix o Vista. Uno de los beneficios reales de C++ es que permite la reutilización y adaptación de códigos existentes y ya bien probados y depurados.
  • 1.8.4. Objetos
El es el centro de la programación orientada a objetos. Un objeto es algo que se visualiza, se utiliza y juega un rol o papel. Si se programa con enfoque orientado a objetos, se intenta descubrir e implementar los objetos que juegan un rol en el dominio del problema y en consecuencia del programa. La estructura interna y el comportamiento de un objeto, en una primera fase, no tiene prioridad. Es importante que un objeto tal como un carro o una casa juegan un rol.

Dependiendo del problema, diferentes aspectos de un dominio son relevantes. Un carro puede ser ensamblado por partes tales como un motor, una carrocería, unas puertas o puede ser descrito utilizando propiedades tales como su velocidad, su kilometraje o su fabricante. Estos atributos indican el objeto. De modo similar una persona, también se puede ver como un objeto, del cual se disponen diferentes atributos. Dependiendo de la definición del problema, esos atributos pueden ser el nombre, apellido, dirección, número de teléfono, color del cabello, altura, peso, profesión, etc.

Un objeto no necesariamente ha de realizar algo concreto o tangible. Puede ser totalmente abstracto y también puede describir un proceso. Por ejemplo, un partido de baloncesto o de rugby  puede ser descrito como un objeto. Los atributos de este objeto pueden ser los jugadores, el entrenador, la puntuación y el tiempo transcurrido de partido.

Cuando se trata de resolver un problema con orientación a objetos, dicho problema no se descompone en funciones como en programación estructurada tradicional, caso de C, sino en objetos. El pensar en términos de objetos tiene una gran ventaja: se asocian los objetos del problema a los objetos del mundo real.

¿Qué tipos de cosas son objetos en los programas orientados a objetos? La respuesta está limitada por su imaginación aunque se pueden agrupar en categorías típicas que facilitarán su búsqueda en la definición del problema de un modo más rápido y sencillo.
  • Recusos Humanos:
             - Empleados.
             - Estudiantes.
             - Clientes.
             - Vendedores.
             - Socios.
  • Colecciones de datos:
             - Arrays (arreglos).
             - Listas.
             - Pilas.
             - Árboles.
             - Árboles binarios.
             - Grafos.
  • Tipos de datos definidos por usuarios:
             - Hora.
             - Números complejos.
             - Puntos del plano.
             - Puntos del espacio.
             - Ángulos.
             - Lados.
  • Elementos de computadoras:
             - Menús.
             - Ventanas.
             - Objetos gráficos (rectángulos, círculos, rectas, puntos...).
             - Ratón (mouse).
             - Teclado.
             - Impresora.
             - USB.
             - Targetas de memoria de cámaras fotográficas.
  • Objetos físicos:
             - Carros.
             - Aviones.
             - Trenes.
             - Barcos.
             - Motocicletas.
             - Casas.
  • Componentes de videojuegos:
             - Consola.
             - Mandos.
             - Volante.
             - Conectores.
             - Memoria.
             - Acceso a Internet.

La correspondencia entre objetos de programación y objetos del mundo real es el resultado eficiente de combinar datos y funciones que manipulan esos datos. Los objetos resultantes ofrecen una mejor solución al diseño del programa que en el caso de los lenguajes orientados a procedimientos.

Un objeto se puede definir desde el punto de vista conceptual como una entidad individual de un sistema y que se caracteriza por un estado y un comportamiento. Desde el punto de vista de implementación, un objeto es una entidad que posee un conjunto de datos y un conjunto de operaciones (funciones o métodos).

El estado de un objeto vienen determinado por los valores que toman sus datos, cuyos valores pueden tener las restricciones impuestas en la definición del problema. Los datos se denominan también atributos y componen la estructura del objeto y las operaciones --también llamadas métodos-- representan los servicios que proporciona el objeto.

La representación gráfica de un objeto en UML se muestra en la Figura 1.6.

 Figura 1.6. Representación de objetos en UML (Lenguaje Unificado de Modelado)

  • 1.8.5. Clases
En POO los objetos son miembros o instancias de clases. En esencia, una clase es un tipo de datos al igual que cualquier otro tipo de dato definido en un lenguaje de programación. La diferencia reside en que la clase es un tipo de dato que contiene datos y funciones. Una clase describe muchos objetos y es preciso definirla, aunque su definición no implica creación de objetos (Figura 1.7).

Una clase es, por consiguiente, una descripción de un número de objetos similares. Madonna, Sting, Prince, Juanes, Carlos Vives o Juan Luis Guerra son miembros u objetos de la clase "músicos de rock". Un objeto concreto, Juanes o Carlos Vives, son instancias de la clase "músicos de rock".

En C++ una clase es una estructura de dato o tipo de dato que contiene funciones (métodos) como miembros y datos. Una clase es una descripción general de un conjunto de objetos similares. Por definición, todos los objetos de una clase comparten los mismos atributos (datos) y las mismas operaciones (métodos). Una clase encapsula las abstracciones de datos y operaciones necesarias para describir una entidad u objeto del mundo real.

 Figura 1.7. Representación de clases en UML.

Una clase se representa en UML mediante un rectángulo que contiene en una banda con el nombre de la clase y opcionalmente otras dos bandas con el nombre de sus atributos y de sus operaciones o métodos (Figura 1.8).

 Figura 1.8. Representación de clases en UML con atributos y métodos.

  • 1.8.6. Generalización y especialización: herencia
La generalización es la propiedad que permite compartir información entre dos unidades evitando la redundancia. En el comportamiento de objetos existen con frecuencia propiedades que son comunes en diferentes objetos y esta propiedad se denomina generalización.
Por ejemplo, máquinas, lavadoras, frigoríficos, hornos de microondas, tostadoras, lavavajillas, etc., son todos los electrodomésticos (aparatos del  hogar). En el mundo de la orientación a objetos, cada uno de estos aparatos es una subclase de la clase Electrodoméstico y a su vez Electrodoméstico es una superclase de todas las otras clases (máquinas, lavadoras, frigoríficos, hornos de microondas, tostadoras, lavavajillas,...).

El proceso inverso de la generalización por el cual se definen nuevas clases a partir de otras ya existentes se denomina especialización.
En orientación a objetos, el mecanismo que implementa la propiedad de generalización se denomina herencia. La herencia permite definir nuevas clases a partir de otras clases ya existentes, de modo que presentan las mismas características y comportamiento de éstas, así como otras adicionales.

La idea de clases conduce a la idea de herencia. Clases diferentes se pueden conectar unas con otras de modo jerárquico. Como ya se ha comentado anteriormente en las relaciones de generalización y especialización, en nuestras vidas diarias se utiliza el concepto de clases divididas en subclases. La clase animal se divide en Anfibios, Mamíferos, Insectos, Pájaros, etc., y la clase Vehículo en Carros, Motos, Camiones, Buses, etc. 
El principio de la división o clasificación es que cada subclase comparte características comunes con la clase de a que procede o se deriva. Los carros, motos camiones y buses tienen ruedas, motores y carrocerías; son las características que definen a un vehículo. Además de las características comunes con los otros miembros de la clase, cada subclase tiene sus propias características. Por ejemplo, los camiones tienen una cabina independiente de la caja que transporta la carga; los buses tienen un gran número de asientos independientemente para los viajeros que ha de transportar, etc. En la Figura 1.9 se muestran clases pertenecientes a una jerarquía o herencia de clases.



De modo similar una clase se puede convertir en padre o raíz de otras subclases. En C++ la clase original se denomina clase base y las clases que se derivan de ella se denominan clases derivadas y siempre son una especialización o concreción de su clase base. A la inversa, la clase base es la generalización de la clase derivada. Esto significa que todas las propiedades (atributos y propiedades) de la clase base se heredan por la clase derivada, normalmente suplementada con propiedades adicionales.
  • 1.8.7. Reusabilidad
Una vez que una clase ha sido escrita, creada y depurada se puede distribuir a otros programadores para utilizar en sus propios programas. Esta propiedad se llama reusabilidad o reutilización. Su concepto es similar a las funciones incluidas en las bibliotecas de funciones de un lenguaje procedimental como C que se puede incorporar en diferentes programas.
En C++, el concepto de herencia proporciona una extensión o ampliación del concepto de reusabilidad. Un programador puede considerar una clase existente y sin modificarla, añadir competencias y propiedades adicionales a  ella. Esto se consigue derivando una nueva clase de una ya existente. La nueva clase heredará las características de la clase antigua, pero es libre de añadir nuevas características propias.

La facilidad de reutilizar o usar el software existente es uno de los grandes beneficios de la POO: muchas empresas consiguen con la reutilización de clases en nuevos proyectos la reducción de los costes de inversión en sus presupuestos de programación. ¿en esencia cuáles son las ventajas de la herencia? Primero se utiliza para consistencia y reducir código, propiedades comunes de varias clases sólo necesitan ser implementadas una vez y sólo necesitan modificarse una vez y si es necesario. Tercero, el concepto de abstracción de la funcionalidad común está soportada.
  • 1.8.8. Polimorfismo
Además de las ventajas de consistencia y reducción de código, la herencia, aporta también otra gran ventaja: facilitar el polimorfismo. Polimorfismo en la propiedad de que un operador o una función actúen de modo diferente en función del objeto sobre el que se aplican. En la práctica el polimorfismo significa la capacidad de una operación de ser interpretada sólo por el propio objeto que lo invoca. Desde un punto de vista práctico de ejecución del programa, el polimorfismo se realiza en tiempo de ejecución ya que durante la compilación no se conoce que tipo de objeto y por consiguiente que operación ha sido llamada.

La propiedad de polimorfismo es aquella en que una operación tiene el mismo nombre en diferentes clases, pero se ejecuta en diferentes formas en cada clase. Así, por ejemplo, la operación de abrir se puede dar en diferentes clases: abrir una puerta, abrir una ventana, abrir un periódico, abrir un archivo, abrir una cuenta corriente en un banco, abrir un libro, etc. En cada caso se ejecuta una operación diferente aunque tiene el mismo nombre en todos ellos "abrir".

El polimorfismo es la propiedad de una operación de ser interpretada sólo por el objeto al que pertenece. Existen diferentes formas de implementar el polimorfismo y variará dependiendo del lenguaje de programación. Veamos el concepto con ejemplos dela vida diaria.

En un taller de reparaciones de automóviles existen numerosos carros (coches), de marcas diferentes, de modelos diferentes, potencias diferentes, etc. Constituyen una clase o colección heterogénea de carros (coches). Supongamos que se ha de realizar una operación común "cambiar los frenos del carro". La operación a realizar es la misma, incluye los mismos principios; sin embargo, dependiendo del coche, en particular, la operación, será muy diferente, incluirá diferentes acciones en cada caso. Otro ejemplo a considerar y relativo a los operadores "+" y "*" aplicados a número enteros o número complejos; aunque ambos son números, en un caso la suma y multiplicación son operaciones simples, mientras que en el caso de los números complejos al componerse de parte real y parte imaginaría, será necesario seguir un método específico para tratar ambas partes y obtener un resultado que también será un número complejo.

El uso de operadores o funciones de forma diferente, dependiendo de los objetos sobre los que están actuando se llama polimorfismo (una cosa con diferentes formas). Sin embargo, cuando un operador existente, tal como + o =, se le permite la posibilidad de operar sobre nuevos tipos de datos, se dice entonces que el operador está sobrecargado. la sobrecarga es un tipo de polimorfismo y una característica importante de la POO.  

-------------------------------------------------------------------------------------------------------------------------------------------------------------------
EJEMPLO 1.8 Definir una jerarquía de clases para: animal, insecto, mamíferos, pájaros, persona hombre y mujer. Realizar una definición en pseudocódigo de las clases.

Las clases de objeto Mamífero, Pájaro e Insecto se definen como subclases de Animal; la clase del objeto Persona, como una subclase de Mamífero, y un Hombre y una Mujer son subclases de Persona



Las definiciones de clases para esta jerarquía puede tomar la siguiente estructura:

clase Animal
  atributos (propiedades)
    string: tipo;
    real: peso;
    (...algun tipo de habitad...):habitad;
  operaciones
    crear () → criatura;
    predatores (criatura) → fijar (criatura);
    esperanza_vida (criatura) entero;
    ...
fin criatura

clase Insecto hereda animal;
    atributos (propiedades)
      cadena: nombre;
    operaciones
    ...
fin insecto

clase Mamifero hereda animal;
    atributos (propiedades)
      real: periodo_gestacion;
    operaciones
    ...
fin Mamifero

clase Pajaro hereda animal;
    atributos (propiedades)
      cadena: nombre;
      entero: alas;
    operaciones
    ...
fin Pajaro

clase Persona hereda Mamifero,
    atributos (propiedades)
      string: apellido, nombre;
      date: fecha_nacimiento;
      pais: origen;
fin persona

clase Hombre hereda persona;
    atributos (propiedades)
      mujer: esposa;
    ...
    operaciones
    ...
fin Hombre

clase Mujer hereda Persona;
    propiedades
      esposo: hombre;
      string: nombre;
    ...
fin mujer
---------------------------------------------------------------------------------------------