Tabla de contenidos
El origen de la revolución informática ocurrió dentro de una máquina. Por tanto, el origen de nuestros lenguajes de programación tiende a parecerse a esa máquina.
Pero los ordenadores no son tanto máquinas como herramientas de amplificación de la mente («bicicletas para la mente», como le gusta decir a Steve Jobs) y un medio de expresión diferente. Como resultado, las herramientas empiezan a parecerse menos a las máquinas y más a partes de nuestra mente, y también a otros medios de expresión como la escritura, la pintura, la escultura, la animación y la cinematografía. La programación orientada a objetos es parte de este movimiento hacia un uso del ordenador como medio de expresión.
Este capítulo le servirá de introducción a los conceptos básicos de la programación orientada a objetos (POO), incluyendo un resumen de los métodos de desarrollo de la POO. Este capítulo, y este libro, presuponen que el lector ya tiene experiencia con un lenguaje de programación procedural, aunque no tiene porqué ser C. Si cree que necesita más preparación en programación y en la sintaxis de C antes de abordar este libro, debería leer el CD-ROM de entrenamiento Thinking in C: Foundations for C++ and Java, que acompaña a este libro, y está disponible también en www.BruceEckel.com.
Este capítulo contiene material básico y suplementario. Mucha gente no se siente cómoda adentrándose en la programación orientada a objetos sin tener antes una visión global. Por eso, aquí se introducen muchos conceptos que intentan darle una visión sólida de la POO. Sin embargo, muchas personas no captan los conceptos globales hasta que no han visto primero parte de la mecánica; puede que se atasquen o se pierdan si no hay ningún trozo de código al que ponerle las manos encima. Si usted pertenece a este último grupo, y está ansioso por llegar a las especificaciones del lenguaje, siéntase libre de saltar este capítulo; eso no le impedirá escribir programas o aprender el lenguaje. Sin embargo, quizá quiera volver a este capítulo para completar sus conocimientos y poder comprender porqué son importantes los objetos y cómo diseñar con ellos.
Todos los lenguajes de programación proporcionan abstracciones. Se puede afirmar que la complejidad de los problemas que se pueden resolver está directamente relacionada con el tipo y calidad de la abstracción. Por «tipo» me refiero a «¿Qué es lo que está abstrayendo?». El lenguaje ensamblador es una pequeña abstracción de la máquina subyacente. Muchos lenguajes llamados «imperativos» que siguieron (como Fortran, BASIC y C) eran abstracciones del lenguaje ensamblador. Estos lenguajes suponen grandes mejoras con respecto al lenguaje ensamblador, pero su abstracción primaria todavía requiere pensar en términos de la estructura del ordenador, en lugar de la estructura del problema que intenta resolver. El programador debe establecer la asociación entre el modelo de la máquina (en el «espacio de soluciones», que es el lugar donde está modelando ese problema, como un ordenador) y el modelo del problema que se está resolviendo (en el «espacio de problemas», que es el lugar donde existe el problema). El esfuerzo requerido para realizar esta correspondencia, y el hecho de que sea extrínseco al lenguaje de programación, produce programas difíciles de escribir y caros de mantener y, como efecto secundario, creó toda la industria de «métodos de programación».
La alternativa a modelar la máquina es modelar el problema que está intentando resolver. Los primeros lenguajes como LISP y APL eligieron concepciones del mundo particulares («Todos los problemas son listas en última instancia», o «Todos los problemas son algorítmicos»). PROLOG reduce todos los problemas a cadenas de decisiones. Se han creado lenguajes para programación basados en restricciones y para programar manipulando exclusivamente símbolos gráficos (lo último demostró ser demasiado restrictivo). Cada uno de estos métodos es una buena solución para el tipo particular de problema para el que fueron diseñados, pero cuando uno sale de ese dominio se hacen difíciles de usar.
El método orientado a objetos va un paso más allá, proporcionando herramientas para que el programador represente los elementos en el espacio del problema. Esta representación es lo suficientemente general como para que el programador no esté limitado a un tipo particular de problema. Nos referimos a los elementos en el espacio del problema, y a sus representaciones en el espacio de la solución, como «objetos» (por supuesto, necesitará otros objetos que no tengan analogías en el espacio del problema). La idea es que permita al programa adaptarse al lenguaje del problema añadiendo nuevos tipos de objetos de modo que cuando lea el código que describe la solución, esté leyendo palabras que además expresan el problema. Es un lenguaje de abstracción más flexible y potente que los que haya usado antes. De esta manera, la POO permite describir el problema en términos del problema, en lugar de usar términos de la computadora en la que se ejecutará la solución. Sin embargo, todavía existe una conexión con la computadora. Cada objeto se parece un poco a una pequeña computadora; tiene un estado y operaciones que se le puede pedir que haga. Sin embargo, no parece una mala analogía a los objetos en el mundo real; todos ellos tienen características y comportamientos.
Algunos diseñadores de lenguajes han decidido que la programación orientada a objetos en sí misma no es adecuada para resolver fácilmente todos los problemas de programación, y abogan por una combinación de varias aproximaciones en lenguajes de programación multiparadigma. [11]
Alan Kay resumió las cinco características básicas de Smalltalk, el primer lenguaje orientado a objetos con éxito y uno de los lenguajes en los que está basado C++. Esas características representan una aproximación a la programación orientada a objetos:
Todo es un objeto. Piense en un objeto como una variable elaborada; almacena datos, pero puede «hacer peticiones» a este objeto, solicitando que realice operaciones en sí mismo. En teoría, puede coger cualquier componente conceptual del problema que está intentando resolver (perros, edificios, servicios, etc.) y representarlos como un objeto en su programa.
Un programa es un grupo de objetos enviando mensajes a otros para decirles qué hacer. Para hacer una petición a un objeto, «envía un mensaje» a ese objeto. Más concretamente, puede pensar en un mensaje como una petición de invocación a una función que pertenece a un objeto particular.
Cada objeto tiene su propia memoria constituida por otros objetos. Visto de otra manera, puede crear un nuevo tipo de objeto haciendo un paquete que contenga objetos existentes. Por consiguiente, puede hacer cosas complejas en un programa ocultando la complejidad de los objetos.
Cada objeto tiene un tipo. Usando el argot, cada objeto es una instancia de una clase, en el que «clase» es sinónimo de «tipo». La característica más importante que lo distingue de una clase es «¿Qué mensajes puede enviarle?»
Todos los objetos de un tipo particular pueden recibir los
mismos mensajes. En realidad es una frase con doble sentido,
como verá más tarde. Como un objeto de tipo
círculo
es también un objeto de tipo
figura
, está garantizado que un círculo
aceptará los mensajes de figura. Esto significa que puede
escribir código que habla con objetos
figura
y automáticamente funcionará con
cualquier otro objeto que coincida con la descripción de
figura
. Esta
sustituibilidad es uno de los conceptos
más poderosos en la POO.