martes, 23 de septiembre de 2014

DISEÑO Y REALIZACIÓN DE SERVICIOS DE PRESENTACIÓN EN ENTORNOS GRÁFICOS UT1

Programación orientada a objetos en C++ y Windows

Conceptos de clase y objeto. Tipos.

Introducción

Los objetos son entidades que tienen un determinado estado, comportamiento (método) e identidad:

El estado está compuesto de datos o informaciones; serán uno o varios atributos a los que se habrán asignado unos valores concretos (datos). El comportamiento está definido por los métodos o mensajes a los que sabe responder dicho objeto, es decir, qué operaciones se pueden realizar con él. La identidad es una propiedad de un objeto que lo diferencia del resto; dicho con otras palabras, es su identificador (concepto análogo al de identificador de una variable o una constante).

Un objeto contiene toda la información que permite definirlo e identificarlo frente a otros objetos pertenecientes a otras clases e incluso frente a objetos de una misma clase, al poder tener valores bien diferenciados en sus atributos. A su vez, los objetos disponen de mecanismos de interacción llamados métodos, que favorecen la comunicación entre ellos. Esta comunicación favorece a su vez el cambio de estado en los propios objetos. Esta característica lleva a tratarlos como unidades indivisibles, en las que no se separa el estado y el comportamiento.

Los métodos (comportamiento) y atributos (estado) están estrechamente relacionados por la propiedad de conjunto. Esta propiedad destaca que una clase requiere de métodos para poder tratar los atributos con los que cuenta. El programador debe pensar indistintamente en ambos conceptos, sin separar ni darle mayor importancia a alguno de ellos. Hacerlo podría producir el hábito erróneo de crear clases contenedoras de información por un lado y clases con métodos que manejen a las primeras por el otro. De esta manera se estaría realizando una programación estructurada camuflada en un lenguaje de programación orientado a objetos.

La POO difiere de la programación estructurada tradicional, en la que los datos y los procedimientos están separados y sin relación, ya que lo único que se busca es el procesamiento de unos datos de entrada para obtener otros de salida. La programación estructurada anima al programador a pensar sobre todo en términos de procedimientos o funciones, y en segundo lugar en las estructuras de datos que esos procedimientos manejan. En la programación estructurada solo se escriben funciones que procesan datos. Los programadores que emplean Programación Orientada a Objetos, en cambio, primero definen objetos para luego enviarles mensajes solicitándoles que realicen sus métodos por sí mismos.
Origen

La programación orientada a objetos se fue convirtiendo en el estilo de programación dominante a mediados de los años ochenta, en gran parte debido a la influencia de C++, una extensión del lenguaje de programación C. Su dominación fue consolidada gracias al auge de las Interfaces gráficas de usuario, para las cuales la programación orientada a objetos está particularmente bien adaptada. En este caso, se habla también de programación dirigida por eventos.

La programación orientada a objetos es una forma de programar que trata de encontrar una solución a estos problemas. Introduce nuevos conceptos, que superan y amplían conceptos antiguos ya conocidos. Entre ellos destacan los siguientes:


Ejemplos:

• Clase Persona (fecha nac., DNI, dir., tel.)
– Jefe (despacho, incentivos, ...)
– Vendedor (área, clientes,...)
– Secretarios

• Clase Forma: área (?), perímetro (?), color
– Rectángulo: dos lados , área, perímetro.
– Cuadrado: un lado, área, perímetro.
– Elipse: dos radios, área
– Circulo: Un radio, área, circunferencia

• Clase Vehículos: Peso
, Potencia, Cilindrada
– Coches: Nº puertas, extras
• Monovolúmenes
• Deportivos.
• Furgonetas
– Camiones: PMA, Tara, Nº ejes.
• Rígidos
• Con remolque
– Motocicletas.
• Con matrícula
• Sin matrícula


Clase
Definiciones de las propiedades y comportamiento de un tipo de objeto concreto. La instanciación es la lectura de estas definiciones y la creación de un objeto a partir de ella.

class CRender {
public:
    char buffer[256]; // atributo
    void m_Renderizar(const char *cadena); // método
};


Herencia
(Por ejemplo, herencia de la clase C a la clase D) es la facilidad mediante la cual la clase D hereda en ella cada uno de los atributos y operaciones de C, como si esos atributos y operaciones hubiesen sido definidos por la misma D. Por lo tanto, puede usar los mismos métodos y variables públicas declaradas en C. Los componentes registrados como "privados" (private) también se heredan, pero como no pertenecen a la clase, se mantienen escondidos al programador y sólo pueden ser accedidos a través de otros métodos públicos. Esto es así para mantener hegemónico el ideal de POO.

Objeto
Instancia de una clase. Entidad provista de un conjunto de propiedades o atributos (datos) y de comportamiento o funcionalidad (métodos), los mismos que consecuentemente reaccionan a eventos. Se corresponden con los objetos reales del mundo que nos rodea, o con objetos internos del sistema (del programa). Es una instancia a una clase.

Método
 Algoritmo asociado a un objeto (o a una clase de objetos), cuya ejecución se desencadena tras la recepción de un "mensaje". Desde el punto de vista del comportamiento, es lo que el objeto puede hacer. Un método puede producir un cambio en las propiedades del objeto, o la generación de un "evento" con un nuevo mensaje para otro objeto del sistema.

Evento
Es un suceso en el sistema (tal como una interacción del usuario con la máquina, o un mensaje enviado por un objeto). El sistema maneja el evento enviando el mensaje adecuado al objeto pertinente. También se puede definir como evento la reacción que puede desencadenar un objeto; es decir, la acción que genera.

Atributos
Contenedor de un tipo de datos asociados a un objeto (o a una clase de objetos), que hace los datos visibles desde fuera del objeto y esto se define como sus características predeterminadas, y cuyo valor puede ser alterado por la ejecución de algún método.


Componentes de un objeto

Atributos, identidad, relaciones y métodos.

Identificación de un objeto

Un objeto se representa por medio de una tabla o entidad que esté compuesta por sus atributos y funciones correspondientes.

En comparación con un lenguaje imperativo, una "variable" no es más que un contenedor interno del atributo del objeto o de un estado interno, así como la "función" es un procedimiento interno del método del objeto.
Características de la POO

Existe un acuerdo acerca de qué características contempla la "orientación a objetos". Las características siguientes son las más importantes:

Abstracción

Denota las características esenciales de un objeto, donde se capturan sus comportamientos. Cada objeto en el sistema sirve como modelo de un "agente" abstracto que puede realizar trabajo, informar y cambiar su estado, y "comunicarse" con otros objetos en el sistema sin revelar cómo se implementan estas características. Los procesos, las funciones o los métodos pueden también ser abstraídos, y, cuando lo están, una variedad de técnicas son requeridas para ampliar una abstracción. El proceso de abstracción permite seleccionar las características relevantes dentro de un conjunto e identificar comportamientos comunes para definir nuevos tipos de entidades en el mundo real. La abstracción es clave en el proceso de análisis y diseño orientado a objetos, ya que mediante ella podemos llegar a armar un conjunto de clases que permitan modelar la realidad o el problema que se quiere atacar.

Encapsulamiento
Significa reunir todos los elementos que pueden considerarse pertenecientes a una misma entidad, al mismo nivel de abstracción. Esto permite aumentar la cohesión de los componentes del sistema. Algunos autores confunden este concepto con el principio de ocultación, principalmente porque se suelen emplear conjuntamente.

Modularidad

Se denomina modularidad a la propiedad que permite subdividir una aplicación en partes más pequeñas (llamadas módulos), cada una de las cuales debe ser tan independiente como sea posible de la aplicación en sí y de las restantes partes. Estos módulos se pueden compilar por separado, pero tienen conexiones con otros módulos. Al igual que la encapsulación, los lenguajes soportan la modularidad de diversas formas.
Principio de ocultación

Polimorfismo

Comportamientos diferentes, asociados a objetos distintos, pueden compartir el mismo nombre; al llamarlos por ese nombre se utilizará el comportamiento correspondiente al objeto que se esté usando. O, dicho de otro modo, las referencias y las colecciones de objetos pueden contener objetos de diferentes tipos, y la invocación de un comportamiento en una referencia producirá el comportamiento correcto para el tipo real del objeto referenciado. Cuando esto ocurre en "tiempo de ejecución", esta última característica se llama asignación tardía o asignación dinámica. Algunos lenguajes proporcionan medios más estáticos (en "tiempo de compilación") de polimorfismo, tales como las plantillas y la sobrecarga de operadores de C++.

Herencia
Las clases no se encuentran aisladas, sino que se relacionan entre sí, formando una jerarquía de clasificación. Los objetos heredan las propiedades y el comportamiento de todas las clases a las que pertenecen. La herencia organiza y facilita el polimorfismo y el encapsulamiento, permitiendo a los objetos ser definidos y creados como tipos especializados de objetos preexistentes. Estos pueden compartir (y extender) su comportamiento sin tener que volver a implementarlo. Esto suele hacerse habitualmente agrupando los objetos en clases y estas en árboles o enrejados que reflejan un comportamiento común. Cuando un objeto hereda de más de una clase se dice que hay herencia múltiple; siendo de alta complejidad técnica por lo cual suele recurrirse a la herencia virtual para evitar la duplicación de datos.


Resumen

La programación orientada a objetos es un paradigma surgido en los años 70, que utiliza objetos como elementos fundamentales en la construcción de la solución. Un objeto es una abstracción de algún hecho o ente del mundo real, con atributos que representan sus características o propiedades, y métodos que emulan su comportamiento o actividad. Todas las propiedades y métodos comunes a los objetos se encapsulan o agrupan en clases. Una clase es una plantilla, un prototipo para crear objetos; en general, se dice que cada objeto es una instancia o ejemplar de una clase.
Lenguajes orientados a objetos

Simula (1967) es aceptado como el primer lenguaje que posee las características principales de un lenguaje orientado a objetos. Fue creado para hacer programas de simulación, en donde los "objetos" son la representación de la información más importante. Smalltalk (1972 a 1980) es posiblemente el ejemplo canónico, y con el que gran parte de la teoría de la programación orientada a objetos se ha desarrollado.

Entre los lenguajes orientados a objetos se destacan los siguientes:


·         ABAP -> SAP Lenguaje orientado a eventos
·         ABL Lenguaje de programación de OpenEdge de Progress Software
·         ActionScript
·         ActionScript 3
·         Ada
·         C++
·         C#
·         Clarion
·         Clipper1
·         D

·         Object Pascal (Embarcadero Delphi)
·         Gambas
·         Genie
·         Harbour
·         Eiffel
·         Fortran 90/95
·         Java
·         JavaScript2
·         Lexico3
·         Objective-C

·         Ocaml
·         Oz
·         R
·         Perl4
·         PHP5
·         PowerBuilder
·         Python
·         Ruby
·         Self
·         Smalltalk6

·         Magik (SmallWorld)
·         Vala
·         VB.NET
·         Visual FoxPro7
·         Visual Basic 6.0
·         Visual DataFlex
·         Visual Objects
·         XBase++
·         Lenguaje DRP
·         Scala8




Muchos de estos lenguajes de programación no son puramente orientados a objetos, sino que son híbridos que combinan la POO con otros paradigmas.

Al igual que C++, otros lenguajes, como OOCOBOL, OOLISP, OOPROLOG y Object REXX, han sido creados añadiendo extensiones orientadas a objetos a un lenguaje de programación clásico.

Un nuevo paso en la abstracción de paradigmas de programación es la Programación Orientada a Aspectos (POA). Aunque es todavía una metodología en estado de maduración, cada vez atrae a más investigadores e incluso proyectos comerciales en todo el mundo.

Ejemplo 1
 
#include <iostream.h>

int main()
{
    Suma s;
    s.setA(80);
    s.setB(100);
    cout << s.getA() << " + " << s.getB() << " = " << s.calcular() << endl;
    cin.get();
    return 0;
}
 
 
 
Ejemplo 2
 
class Suma
{
    // atributo privado     
    double resultado;
 
public:
    // método público
    double calcular();
 
    // atributo público
    Pareja  p;
};
 
// implementación del metodo calcular de la clase Suma.
double Suma::calcular() { return p.getA() + p.getB(); }




Estructuras asociadas a objetos. Constructores y destructores. Punteros y arrays.

Constructores.
Cuando creamos un objeto de una clase, siempre seguimos los mismos pasos para llamar a un conjunto de métodos que inicialicen los datos del objeto. En EL LENGUAJE C++, se define una función especial, el constructor, que es llamada cuando se crea un nuevo objeto de la clase. Este constructor puede recibir parámetros, como cualquier otra función. Veamos un ejemplo de clase sin constructor y con constructor:

# include <iostream.h>
class Caja {
double longitud, anchura, altura;
public:
Caja (double dim1, double dim2, double dim3);
double volumen (void);
};
Caja:: Caja (double dim1, double dim2, double dim3) {
longitud = dim1;
anchura = dim2;
altura = dim3;
};
double Caja:: volumen (void) {
return longitud * anchura * altura;
};
main () {
Caja pequeña(5, 4, 10), mediana (10, 6, 20), grande(20, 10, 30);
cout << 'El volumen de la caja grande es ' << grande.volumen() << '\n';
}
En este sencillo ejemplo vemos las características más importantes de un constructor:
· El constructor tiene el mismo nombre que la clase a la que pertenece. Por ejemplo, el constructor de la clase Caja se llama Caja.
· El constructor no devuelve nada (ni siquiera void).
· Los argumentos se pasan al constructor en la declaración de un objeto. Así, Caja pequeña (5, 4, 10) crea un nuevo objeto de la clase Caja y llama al constructor con los parámetros 5, 4 y 10.
Cuando se crea un objeto de una clase, se llama automáticamente al constructor. Si tuviésemos un puntero a una clase, su constructor no seria llamado a menos que reserváramos memoria para lo que apunta el puntero, utilizando new.
Un constructor es una función, y por tanto podemos aplicarle todo lo que hemos visto que las funciones EN EL LENGUAJE C++ pueden hacer. Por ejemplo, podemos sobrecargarlo:

# include <iostream.h>
class Caja {
double longitud, anchura, altura;
public:
Caja (double dim1, double dim2, double dim3);
Caja (void);
double volumen (void);
};
Caja:: Caja (void) {
longitud = 8;
anchura = 8;
altura = 8;
};

Hemos creado una función constructora que inicializa las dimensiones de la caja a 8. Esta será llamada cuando creemos un objeto del tipo Caja sin ningún parámetro.
Destructores.
El destructor es muy similar al constructor, excepto que es llamado automáticamente cuando cada objeto sale de su ámbito de validez. Recordemos que las variables automáticas tienen un tiempo de vida limitado, ya que dejan de existir cuando se sale del bloque en que han sido declaradas. Cuando un objeto es liberado automáticamente, su destructor, si existe, es llamado automáticamente.
Un destructor tiene el mismo nombre que la clase a la que pertenece, pero precedido con una tilde (~). Igual que el constructor, un destructor no devuelve nada.
Si algún bloque de memoria fue reservado dinámicamente en un objeto, se puede utilizar el destructor para liberarlo antes de que se pierdan los punteros a esas variables.

#include <iostream.h>
class Taco
{
   public:
  Taco (int hard) {
  dureza = new int;
  *dureza = hard;
}
~Taco() {
     cout << 'Destruyendo taco con dureza ' ;
     cout << *dureza <<;\n';
     delete dureza;
}
private:
int *dureza;
};
main () {
   Taco hard(10);
   Taco *soft = new Taco (0);
   delete soft;
};

En este ejemplo, vemos que el destructor tiene el mismo nombre que la clase, con un ~ delante. Cuando se crean punteros a clases, como soft en el ejemplo, se llama al destructor cuando se libera la memoria del puntero. Si esto no se hace, nunca se llamara al destructor.
Con clases declaradas estáticamente, como Taco hard, el destructor se llama al final de la función donde se declara el objeto (en el ejemplo, al final de la función main.
Incluso cuando se interrumpe un programa usando una llamada a exit(), se llama a los destructores de los objetos que existen en ese momento.

Punteros a objetos

Los punteros a objetos se declaran como cualquier otro tipo de puntero:

CComplejo* pc;

Puesto que pc es un puntero y no un objeto, su declaración no lleva implícita la ejecución del constructor, y por lo tanto no está inicializado: pc apunta a cualquier posición de memoria justo después de haber sido declarado. Un puntero a objeto se manipula como cualquier otro tipo de puntero. En particular, para crear la variable dinámica apuntada por el puntero pc, debe emplearse el operador new; para enviar mensajes al objeto apuntado por pc, debe emplearse el operador ->;  y finalmente, para liberar el objeto apuntado por pc debe emplearse el operador delete:

CComplejo* pc;
pc= new CComplejo;
pc->asigna_real(3);
pc->asigna_imag(6);
//...
delete pc;



Herencia y polimorfismo.

Hasta ahora hemos visto cómo definir clases en C++ y una serie de características de estas últimas, como la forma de crear objetos, de declarar miembros con distintos tipos de acceso, etcétera. Pero todas estas características son tan sólo una parte de la historia. Dijimos que el uso de objetos se introducía para representar conceptos del mundo de nuestro programa en una forma cómoda y que permitían el uso de las clases como tipos del lenguaje, pero, ¿cómo representamos las relaciones entre los objetos?, es decir,  ¿cómo indicamos la relación entre las personas y los empleados, por ejemplo?.

Esto se consigue definiendo una serie de relaciones de parentesco entre las clases. Definimos las clases como antes, pero intentamos dar  unas clases base o clases padre  para representar las características comunes de las clases y luego definimos unas clases derivadas o subclases que definen tan sólo las características diferenciadoras de los objetos de esa clase. Por ejemplo, si queremos representar empleados y clientes podemos definir una clase base persona que contenga las características comunes de ambas clases (nombre, Cedula, etc.) y después declararemos las clases empleado y cliente como derivadas de persona, y sólo definiremos los miembros que son nuevos respecto a las  personas
o los que tienen características diferentes en la clase derivada, por ejemplo un empleado puede ser despedido, tiene un sueldo, puede firmar un contrato, etc.,  mientras que un cliente puede tener una  cuenta, una lista de pedidos, puede firmar un contrato, etc. Como se ha mencionado ambos tipos pueden firmar contratos, pero los métodos serán diferentes, ya que la acción es la misma pero tiene significados distintos.

En definitiva, introducimos los mecanismos de la herencia y  polimorfismo para implementar las relaciones entre las clases. La herencia consiste en la definición de clases a partir de otras clases, de tal forma que la clase derivada hereda las características de la clase  base, mientras que el polimorfismo nos permite que métodos declarados de la misma manera en una clase base y una derivada se comporten de forma distinta en función de la clase del objeto que la invoque, el método es polimórfico, tiene varias formas.

Clases derivadas o subclases

Clases derivadas

Una clase derivada es una clase que se define en función de otra clase. La sintaxis es muy simple, declaramos la clase como siempre, pero después de nombrar la clase escribimos dos puntos y el nombre de su clase base. Esto le indica al compilador que todos los miembros de la clase base se heredan en la nueva clase. Por ejemplo, si tenemos la clase empleado (derivada de persona) y queremos definir la clase  directivo podemos declarar esta última como derivada de la primera. Así, un directivo tendrá las características de persona y de empleado, pero definirá además unos nuevos atributos y métodos propios de su clase:

class directivo : empleado {
private:
long num_empleados;
long num_acciones;
...
public:
...
void despide_a (empleado *e);
void reunion_con (directivo *d);
...
};

Como un objeto de tipo directivo es un empleado, se podrá usar en los lugares en los que se trate a los empleados, pero no al revés (un empleado no puede usarse cuando necesitamos un directivo). Esto es cierto cuando trabajamos con punteros a objetos, no con objetos:

directivo d1, d2; empleado e1;
lista_empleados *le;
le= &d1; // inserta un directivo en la lista de empleados
d1.next = &e1; // el siguiente empleado es e1
e1.next = &d2; // el siguiente empleado es el directivo 2
d1.despide_a (&e1); // el directivo puede despedir a un empleado
d1.despide_a (&d2); // o a otro directivo, ya que también es un empleado
e1.despide_a (&d1); // ERROR, un empleado no tiene definido el método despide a
d1.reunion_con (&d2); // Un directivo se reúne con otro
d1.reunion_con (&e); // ERROR, un empleado no se reúne con un directivo
empleado *e2 = &d2; // CORRECTO, un directivo es un empleado
directivo *d3 = &e; // ERROR, no todos los empleados son directivos
d3->num_empleados =3; // Puede provocar un error, ya que e1 no tiene espacio
// reservado para num_empleados
d3 = (directivo *)e2. // CORRECTO, e2 apunta a un directivo
d3->num_empleados =3; // CORRECTO, d3 apunta a un directivo

En definitiva, un objeto de una clase derivada se puede usar como objeto de la clase base si se maneja con punteros, pero hay que tener cuidado ya que el C++ no realiza chequeo de tipos dinámico (no tiene forma de saber que un puntero a un tipo base realmente apunta a un objeto de la clase derivada).

Concepto de interfaz gráfica

Conocida también como GUI (del inglés graphical user interface) es un programa informático que actúa de interfaz de usuario, utilizando un conjunto de imágenes y objetos gráficos para representar la información y acciones disponibles en la interfaz. Su principal uso, consiste en proporcionar un entorno visual sencillo para permitir la comunicación con el sistema operativo de una máquina o computador.

Habitualmente las acciones se realizan mediante manipulación directa, para facilitar la interacción del usuario con la computadora. Surge como evolución de las interfaces de línea de comandos que se usaban para operar los primeros sistemas operativos y es pieza fundamental en un entorno gráfico. Como ejemplos de interfaz gráfica de usuario, cabe citar los entornos de escritorio Windows, el X-Window de GNU/Linux o el de Mac OS X, Aqua.

En el contexto del proceso de interacción persona-ordenador, la interfaz gráfica de usuario es el artefacto tecnológico de un sistema interactivo que posibilita, a través del uso y la representación del lenguaje visual, una interacción amigable con un sistema informático.

La librería ObjectWindows.

Biblioteca de objetos de Windows , más conocido por la sigla OWL, es una biblioteca de clases C + + producido por Borland con el fin de encapsular la API de Windows.

PPP fue lanzado por Borland por su compilador de Borland C + + en gran parte al mismo tiempo que Microsoft había lanzado un producto de la competencia llamada Microsoft Foundation Classes . Desde PPP tenía una estructura superior biblioteca orientada a objetos de Microsoft, durante un tiempo fue mucho más exitosa, sin embargo, la pérdida de cuota de mercado cuando las actualizaciones no soporta las nuevas características de Windows, y luego nunca se produjo. Actualmente un grupo independiente (equipo OWLNext) es responsable de actualizar y proporcionar nuevas características.

No hay comentarios:

Publicar un comentario