En muchas ocasiones la programacion orientada a objetos (OOP) puede convertirse en una forma excesivamente compleja de resolver un problema, en especial si se trata de un problema simple. Pero el nivel de abstracción que ofrece esta metodología permite acometer problemas complejos de forma mucho más simple que la programación clásica. A pesar de que ya hemos hecho uso de este tipo de técnicas en los artículos anteriores, en el presente trataremos de centrarnos en las características que diferencian a estas técnicas.
En la actualidad los grandes problemas del mundo real se están descomponiendo, desde el punto de vista de programación, en objetos que encierran ciertas características y engloban no solamente a los datos sino también a las funciones relacionadas y que operan con ellos. Esto permite la modularidad, el encapsulado, polimorfismo y la herencia, que son las características principales de la programación orientada a objetos.
Programacion Orientada a Objetos
Diferencias y evolución de la programación estructurada a la OOP.
- La programación estructurada se caracteriza por un enfoque top-down con estructuras orientadas a bloques en las que el código fuente se divide muchas veces en bloques dependientes de las sentencias condicionales, bucles, etc. Este tipo de programación es apropiada para el diseño de pequeños programas, en los que no se requiere de los recursos adicionales que puede necesitar una aplicación orientada a objetos. En el caso de tener que abordar grandes problemas, la metodología top-down opta por descomponer el problema en otros de menor tamaño de forma sucesiva hasta que la complejidad de cada uno de estos subproblemas es tratable directamente. Una de las principales desventajas de la programación estructurada es que resulta muy difícil reutilizar el trabajo hecho para poder aplicarlo en otros proyectos.El Pascal es el lenguaje de programación estructurada clásico por excelencia. El auge de este tipo tipo de programación se produjo en la década de los años 70 a los 80, y sus carencias irían superámdose con el diseño denominado bottom-up, en el que se trabaja de modo inverso al modo anterior: se parte de pequeños problemas que ya han sido resueltos previamente, de forma que se puede reutilizar código, y se trata de avanzar hacia la solución del problema global mediante estos componente de software ya existentes. El éxito de esta metodología pasa por un diseño modular de componentes, en el que deberán especificarse y documentarse correctamente estos módulos para facilitar su reutilización posterior.Desde el momento en el que disponemos de varios de los módulos anteriores y nos disponemos a crear una nueva aplicación haciendo uso de dichos módulos, lo único que nos interesa conocer es cómo debemos hacer uso de los mismos, pero sin importarnos su implementación interna, los datos o los procedimientos que contiene. Es decir, estaremos interesados exclusivamente en lo que se denomina como el interfaz del módulo, y el hecho de poder despreocuparnos del interior de esos módulos se denomina information hiding, que es la base de la ingeniería del software.
- La evolución final de la idea anterior acabó por plasmarse en lo que hoy se conoce como la programación orientada a objetos. La OOP es más apropiada en proyectos de cierta envergadura, en donde la modularidad de los objetos facilita la labor del programador y favorece la reutilización del código. En este caso pueden emplearse diferentes clases para representar áreas de funcionalidad diferente. El Java o el C++ son dos de los más populares lenguajes de programación orientada a objetos.En términos generales podemos decir que los programas estructurados son más fáciles de entender -sin que ello implique que sean más fáciles de mantener- y de ejecución más rápida. En la actualidad se ha extendido ampliamente la programación orientada a objetos y el pilar sobre el que se sustenta es la reutilización de código. La idea es ir construyendo una librería de código a medida que vamos programando, con objeto de que cuando tengamos que crear una nueva aplicación podamos comprobar previamente si algunos de los módulos ya creados pueden ser reutilizados. Esto conlleva una cultura entre los programadores involucrados, que les obligue a tener presente al programar que no tratamos sólo de resolver un problema puntual actual, sino que además pretendemos que el tiempo invertido en ello pueda ser amortizado reutilizando dichos módulos en el futuro.La reutilización de código tiene varias ventajas, como:
- Fiabilidad, porque se trabaja con módulos ya probados. La reutilización de estos módulos en aplicaciones diferentes por varios diseñadores permitirá la detección de problemas no conocidos, lo que puede retroalimentarse para optimizar el código.
- Eficiencia.
- Reducción de costes.
- Consistencia, la creación de las librerías de código obliga a homologar o estandarizar la forma de programar entre todos los programadores.
- Llegados a este punto conviene definir más concretamente qué es un objeto y una clase, así como sus propiedades.Una clase es una definición abstracta de un objeto. En esta definición se engloban tanto las características del objeto, sus propiedades y también las funciones para operar con ellos. Pero una clase no representa a un objeto concreto sino que no es nada más que una caracterización o definición: la implementación se materializa cuando creamos al objeto como perteneciente a una clase determinada. Este proceso de creación del objeto suele denominarse instanciación.
El enfoque anterior, basado en clases, es el más extendido en el mundo de la programación OO, y con ella trabajan lenguajes como Java o C++. Pero existe una alternativa a la propuesta basada en clases: es la basada en prototipos. Esta segunda propuesta crea los objetos mediante un proceso denominado de clonación sobre el prototipo, que no es otra cosa que un estereotipo que proporciona la base o estructura para la operación de copiado. Esta alternativa está menos extendida que la primera.
- Describamos las propiedades generales de los objetos:
- Encapsulación. Esta es la propiedad que permite ocultar la información. En un mundo dominado por la información como el nuestro, podríamos preguntarnos para qué puede servir la posibilidad de ofuscar cierta información. El objetivo de esto no otro que el de presentar a un objeto a través de un interfaz que oculte los detalles que no son necesarios para operar con un objeto. En muchas ocasiones simplemente queremos realizar ciertas operaciones con objetos, y nos tiene sin cuidado cómo han sido implementados éstos internamente: el encapsulado es la propiedad que lo permite.
- Polimorfismo. Es la propiedad que permite asignar un diferente significado o aplicar un uso determinado dependiendo del contexto en el que se emplea:
1) Aplicado a una variable, por ejemplo USUARIO, si permitimos que la variable usuario pueda tener varias formas, como que pueda ser de tipo entero, o de tipo string, entonces el programa debería elegir cuál de esas formas debería aplicar al ejecutar el código. De este modo, si empleamos un formulario que acepte como datos de entrada los provenientes de la variable USUARIO, estaríamos permitiendo la posibilidad de que el registro de entrada se realice bien con un nº de usuario, o bien con una secuencia de caracteres. El programa debería tener previsto qué hacer en cada caso.
2) Si aplicamos el polimorfismo a un método nos encontrarnos con el concepto denominado overload (sobrecarga): Los métodos sobrecargados son aquellos qie mantienen el nombre dentro de la misma clase. Al sobrecargar un método modificamos su funcionalidad dependiendo del tipo de parámetros de entrada que éste recibe (lo cual viene especificado por su declaración): De hecho el criterio que determina si los métodos sobrecargados en Java pueden compilar es que las listas de parámetros de los métodos sobrecargados puedan determinar el método al que llamar. Así, podemos crear dos métodos con el mismo nombre: es importante por ello reseñar la diferencia en la declaración de los dos métodos empleados para ello, puesto que dependiendo de los parámetros recibidos y de dichas definiciones el compilador deberá seleccionar qué método emplear:
public int sum(int num1, int num2); } ... } public string sum(string cad1, string cad2); } ... }
- La herencia es una característica que permite la reutilización del código y facilita la extensibilidad del software. Gracias a ella podemos crear nuevas clases partiendo de una jerarquía de clases ya existente, lo que evita tanto el rediseño, como tener que volver a verificar el código ya probado. Del mismo modo se facilita la creación de objetos a partir de otros ya existentes, obteniendo características (métodos y atributos) similares a los ya existentes. La herencia es la relación entre una clase general y otra clase más especifica: permite crear una clase derivada a partir de una primera clase, que se denomina superclase.
Relacionando el presente artículo con el LEGO MINDSTORMS, nos encontramos que si requerimos de un lenguaje orientado a objetos para programar el NXT podemos hacerlo básicamente con LeJOS, la versión Java para NXT. Por otro lado disponemos del Lua: aunque Lua no es un lenguaje orientado a objetos en sentido estricto, dispone de meta-mecanismos que permiten la implementación de clases y la herencia.