Вы находитесь на странице: 1из 14

2011

POO Antonio

[PROGRAMACION ORIENTADA A OBJETOS]


Una explicacin sencilla a este nuevo paradigma

Programacin orientada a objetos


Este texto lo saque del siguiente blog: http://blog.smaldone.com.ar/2006/10/27/programacion-orientada-aobjetos/ creo que explica bastante bien los conceptos de clase, objeto, herencia y polimorfismo, me pareci interesante as que se los dejo para lo que lo lean.

Cuando comenc a explorar la programacin orientada a objetos (POO u OOP, en ingls), all por el ao 1994, me ocurri lo que a muchos. Luego de casi 10 aos de programar proceduralmente (en Basic, Pascal y Cobol) me encontraba con una nueva visin. Si bien crea entender los conceptos de clase, objeto, herencia y polimorfismo, no lograba ver claramente la diferencia de enfoque a la hora de disear un programa. No poda apreciar realmente cules eran las diferencias y las similitudes entre el enfoque procedural y el orientado a objetos. A travs de mi experiencia docente varias veces me vi frente a la tarea de introducir los conceptos bsicos de la POO, encontrndome con la misma situacin, pero desde un lugar diferente: Cmo explicar el nuevo enfoque a personas acostumbradas a programar de forma procedural? Cmo resaltar las similitudes y las diferencias? Fue gracias a un ejemplo del libro C++ Annotations que encontr una forma simple de presentar la idea bsica detrs de la programacin orientada a objetos. Una consideracin ms que necesaria: este artculo no se trata de un anlisis profundo de la programacin orientada a objetos, sino simplemente de una simple y breve introduccin, intentando dar un panorama inicial a aquellos que no han tenido contacto con (o nunca han entendido) la POO.

Aclaraciones previas Antes de desarrollar el ejemplo, aclararemos algunos conceptos que muchas veces se prestan a confusin: Lenguajes imperativos: Son aquellos basados en sentencias, ya sean procedurales, orientados a objetos puros o mixtos. Entre ellos se cuentan Pascal, C, C++, Java, Fortran, Perl y Python. Lenguajes procedurales: Son lenguajes imperativos basados en procedimientos (o rutinas) y funciones. Entre ellos podemos nombrar a C, Fortran, Pascal (estndar) y Basic. Lenguajes orientados a objetos: Son lenguajes imperativos basados en clases (algunos, llamados mixtos soportan tambin el modelo procedural). Entre los lenguajes orientados a objetos puros podemos nombrar a Smalltalk, Eiffel y Java. Entre los mixtos se encuentran C++ y Python. Lenguajes funcionales: Son aquellos basados en funciones matemticas (y no en comandos o sentencias). Podemos nombrar aqu a ML, Haskell y Lisp. Un programa procedural simple Vamos a plantear un ejemplo sencillo. Para ello supondremos un lenguaje imperativo con una sintaxis similar a la de Pascal (usaremos este lenguaje ficticio para simplificar la explicacin, en los apndices al final del artculo podr encontrar ejemplos equivalentes en PHP, Python y Eiffel).

Supongamos que tenemos el siguiente programa: program personas; type persona = record nombre: string; apellido: string; edad: integer end; procedure inicializar(n, a: string; e: integer; var p: persona); begin p.nombre := n; p.apellido := a; p.edad := e end; function es_mayor(p: persona): boolean; begin return p.edad >= 18 end; function nombre_completo(p: persona): string; begin return p.nombre + " " + p.apellido; end; var p: persona; begin inicializar("Juan", "Perez", 25, p); write(nombre_completo(p)); if (es_mayor(p)) then writeln (" es mayor de edad." else writeln (" es menor de edad." end.

El programa es bastante sencillo. Primero declaramos un tipo persona que es un registro que contiene los campos nombre, apellido y edad. Luego definimos el procedimiento inicializar que toma el nombre, el apellido, la edad y la persona y asigna los primeros a los campos correspondientes de la ltima. Luego, un par de funciones (es_mayor y nombre_completo) toman una persona y realizan clculos sobre los valores de sus campos. En los programas procedurales hacemos esto todo el tiempo: definimos estructuras y tipos de datos y luego creamos procedimientos y funciones que toman como parmetros variables de estos tipos y realizan distintas operaciones sobre ellos. Dicho de otra manera: podemos ver a los programas procedurales como un conjunto de procedimientos y funciones que manipulan estructuras de datos pasadas como parmetros. Una visin diferente Podramos intentar una visin distinta de la situacin. Supongamos que nuestro lenguaje nos permite definir acciones y funciones dentro de un registro. Supongamos adems que dichas funciones pueden acceder a todos los campos del registro. De esta forma, por ejemplo, el procedimiento inicializar no necesitara del parmetro p (la persona a inicializar), sino que actuara sobre la persona a la que pertenece (ya que se encuentra definido dentro del registro. De esta forma, podramos reescribir el programa como sigue: program personas; type persona = record nombre: string; apellido: string; edad: integer; procedure inicializar(n, a: string; e: integer); begin nombre := n; apellido := a;

edad := e end; function es_mayor: boolean; begin return edad >= 18 end; function nombre_completo: string; begin return nombre + " " + apellido; end end; var p: persona; begin p.inicializar("Juan", "Perez", 25); write(p.nombre_completo); if (p.es_mayor) then writeln (" es mayor de edad." else writeln (" es menor de edad." end. Esta visin alternativa tiene varias ventajas. Inmediatamente notamos que los perfiles de los procedimientos y funciones se simplifican, debido a la eliminacin del parmetro que representa a la persona sobre/con la cual se realizarn las operaciones. Una diferencia importante de notacin a la hora de usar la estructura de datos definida, es que ya no utilizamos expresiones de la forma funcion(variable), sino que ahora escribimos variable.funcion. Una ventaja adicional es que la notacin es ms consistente. Al referirnos a p.nombre_completo no podemos saber (porque en realidad no interesa) si nombre_completo es un campo del registro o una funcin. Esto es realmente importante: en el caso del campo edad este podra ser reemplazado por una funcin que calcule la edad de la

persona, aadiendo un campo que represente la fecha de nacimiento. De ocurrir esto, los programas que usen el tipo persona no requeriran mayores modificaciones, ya que podran seguir haciendo referencia a p.edad. Esto facilita la independencia de la implementacin y el encapsulamiento, uno de los conceptos claves de la POO. Ajustando nuestro vocabulario A lo que antes llambamos tipo, refirindonos a estructuras de datos, ahora lo llamamos clase, entendiendo como tal no slo las estructuras, sino tambin el comportamiento asociado (las acciones y funciones asociadas directamente con la estructura de datos). A lo que antes llambamos variable ahora lo llamamos objeto. As como las variables son de determinado tipo, los objetos son de determinada clase. Los procedimientos y funciones definidos dentro de una clase se llaman mtodos, en tanto que los campos se denominan atributos. En nuestro ejemplo, podramos decir que la clase persona tiene los atributos nombre, apellido y edad, y los mtodos inicializar, nombre_completo y es_mayor. Un concepto importante: La herencia En la POO existe la posibilidad de extender el comportamiento de una clase, aadiendo atributos y mtodos. El mecanismo utilizado para tal fin se denomina herencia. Siguiendo con nuestro ejemplo, podramos querer definir una clase empleado. Bsicamente un empleado posee todas las y caractersticas de una persona (tiene nombre y apellido, tiene sentido preguntarse si es mayor de edad, etc.). Sin embargo, un empleado tendr otros atributos (por ejemplo, un salario, un cargo) y tambin otros mtodos (liquidar_salario, etc.). Es por esto que bastar con definir a la clase

empleado heredando de la clase persona (en POO se usa la expresin un empleado es una persona), y aadiendo el nuevo comportamiento (mtodos y atributos). El secreto: un cambio de visin La POO no es, como muchos afirman, un paradigma distinto del de la programacin procedural. Ambas son dos tcnicas distintas para abordar la programacin imperativa. El secreto fundamental consiste en dejar de ver a un programa como un conjunto de acciones y funciones que modifican parmetros, para verlo como un conjunto de objetos con comportamiento, y a estos como estructuras que contienen acciones y funciones. Si bien la POO involucra una serie de conceptos que escapan al alcance de este texto introductorio, el cambio de visin no es mucho ms profundo que el pequeo truco que hemos realizado al incorporar a las funciones dentro de una estructura. Recomendaciones finales La POO representa un gran avance en la programacin, tal como lo fue la programacin estructurada en la dcada de los 70. Entre sus ventajas ms importante se encuentran un notable aumento de la productividad del programador y de la robustez de los programas. Personalmente, el lenguaje orientado a objetos que ms me agrada es Eiffel (adems de sus caractersticas de orientacin a objetos, soporta la metodologa de diseo por contratos). Otro lenguaje muy bien diseado (y de uso creciente) es Ruby. Tambin es recomendable, y muy simple para comenzar, el lenguaje Python.

Apndice: Un ejemplo en PHP He agregado este apndice siguiendo la sugerencia de un amigo (gracias, Santi) sobre la conveniencia de contar con un ejemplo concreto utilizando el lenguaje PHP, debido a que el mismo es usado por un gran nmero de personas sin una formacin formal en programacin. El ejemplo inicial, usando programacin procedural, sera como sigue: <? function inicializar($nombre, $apellido, $edad) { $persona['nombre'] = $nombre; $persona['apellido'] = $apellido; $persona['edad'] = $edad; return $persona; } function nombre_completo($persona) { return $persona['nombre'] . ' ' .$persona['apellido']; } function es_mayor($persona) { return $persona['edad'] >= 18; } $p = inicializar('Juan', 'Perez', 25); echo nombre_completo($p); if (es_mayor($p)) { echo " es mayor de edad.n"; } else { echo " es menor de edad.n"; } ?> Inmediatamente notamos una gran diferencia respecto del ejemplo en Pascal: en PHP nunca definimos un tipo persona ni su estructura. Esto dificulta la comprensin del programa, ya que solamente

inspeccionando la funcin inicializar podemos ver qu campos contiene el arreglo asociativo persona. Todo esto se debe a que PHP es un lenguaje con un sistema de tipos dinmico (una caracterstica que lo hace muy simple y rpido para pequeos desarrollos, pero que se vuelve un arma de doble filo en programas complejos). La versin orientada a objetos de este mismo programa sera la siguiente: <? class Persona { var $nombre; var $apellido; var $edad; function Persona($nombre, $apellido, $edad) { $this->nombre = $nombre; $this->apellido = $apellido; $this->edad = $edad; } function nombre_completo() { return $this->nombre . ' ' . $this->apellido; } function es_mayor($persona) { return $this->edad >= 18; } } $p = new Persona('Juan', 'Perez', 25); echo $p->nombre_completo(); if ($p->es_mayor) { echo " es mayor de edad.n"; } else { echo " es menor de edad.n"; } ?>

Este ejemplo nos permite introducir otro concepto de la POO: el uso de constructores. Un constructor es una funcin de una clase que se ejecuta automticamente al crear un objeto (instancia). En el caso de PHP (y de varios otros lenguajes) el constructor debe tener el mismo nombre que la clase (en nuestro ejemplo, Persona). La sentencia $p = new Persona(Juan, Perez, 25); crea un nuevo objeto ($p), de la clase Persona, ejecutando la funcin Persona (que reemplaza a la antigua funcin inicializar) con los parmetros Juan, Perez y 25. Otra diferencia respecto del ejemplo anterior, es la utilizacin del operador -> como selector de mtodos y atributos de un objeto. En la definicin de la clase Persona, $this es una referencia al objeto actual, necesaria para determinar el alcance de las variables utilizadas (para acceder al atributo nombre de la clase, debemos escribir $this>nombre, ya que $nombre sera interpretado como una nueva variable). Si usted programa en PHP le recomiendo la utilizacin de POO (en particular, la versin 5 mejora mucho las caractersticas de orientacin a objetos del lenguaje). Apndice: un ejemplo en Python A continuacin, un ejemplo de la versin orientada a objetos utilizando el lenguaje Python: class Persona: def __init__(self, nombre, apellido, edad): self.nombre = nombre self.apellido = apellido self.edad = edad def nombre_completo(self): return self.nombre + ' ' + self.apellido def es_mayor(self):

return self.edad >= 18 p = Persona('Juan', 'Perez', 25) print p.nombre_completo(), if p.es_mayor: print "es mayor de edad." else: print "es menor de edad."

Como podemos apreciar, el constructor de la clase se declara como __init__, en tanto que la referencia al objeto actual se llama self (y debe aparecer como primer parmetro de todos los mtodos de la clase, aunque no se utiliza en la invocacin de los mismos). Python es un lenguaje muy simple, pero caben aqu las mismas consideraciones hechas para PHP, respecto de los lenguajes con sistemas de tipos dinmicos. Apndice: un ejemplo en Eiffel Finalmente, un ejemplo en mi lenguaje de programacin orientado a objetos favorito: Eiffel. A continuacin la definicin de la clase persona: class PERSONA creation make feature nombre: STRING; apellido: STRING; edad: INTEGER; make(n, a: STRING; e: INTEGER) is do nombre := n apellido := a edad := e end nombre_completo: STRING is

do Result := nombre + " " + apellido end es_mayor: BOOLEAN is do Result := edad >= 18 end end Debemos recordar que Eiffel (a diferencia de los dems lenguajes utilizados como ejemplo) es totalmente orientado a objetos (o puro, como suele decirse). Es por esto que no hay diferencia entre las clases y el programa principal, siendo este tambin una clase (llamada raz o ROOT). A continuacin, el cdigo de la clase ROOT: class ROOT creation make feature make is local p: PERSONA do create p.make("Juan", "Perez", 25) print(p.nombre_completo) if p.es_mayor then print(" es mayor de edad.%N" else print(" es menor de edad.%N" end end end Podemos notar que los nombres de clases se escriben con maysculas,

en tanto que el lenguaje permite especificar cul es el constructor de cada clase (en este caso, el mtodo make). Vemos tambin que sin ver el cdigo de la clase PERSONA es imposible saber si nombre_completo es un atributo (variable) o un mtodo (funcin). Esto, como habamos sealado al comienzo del artculo, es una ventaja (ntese que en PHP y en Python no ocurre lo mismo), ya que podemos cambiar la implementacin de la clase, sin alterar el resto del programa. Al tener un sistema de tipos fuerte y esttico, Eiffel nos obliga a declarar el tipo de cada variable o parmetro utilizado, permitiendo as que el compilador detecte posibles errores antes de la ejecucin del programa.

Вам также может понравиться