OOP(II)-Comprendiendo la orientación a objetos

Si antes estuvimos hablando de clases y objetos, nuestro segundo artículo empieza analizando conceptos sin que no se comprendería la orientación a objetos, y que son: Abstracción, Polimorfismo, Herencia y Encapsulación. Puede que las veáis como palabras extrañas, pero creo que os podré convencer que definen conceptos terriblemente sencillos y que utilizamos en nuestra vida diaria

Abstracción

La abstracción es algo que venimos practicando desde pequeños. Cada vez que vemos algo, nuestra mente va asimilándolo a cosas conocidas, de tal forma que llegamos a crear conceptos genéricos sin darnos cuenta. Si yo te hablo de un árbol, automáticamente sabes a que me estoy refiriendo ya que tienes una abstracción realizada para el sustantivo árbol.

En esa abstracción no se determina la altura, el color, el numero de ramas, la especie y todos esos detalles concretos que yo no he mencionado…

Tu imagen mental de “árbol” (tu abstracción ) puede que sea distinta a la mía, pero los atributos principales coincidirán:

  • tendrá color
  • tendrá ramas,
  • tendrá tronco

y podrá:

  • crecer()
  • secarse()
  • morir()

en cambio, no tendrá puertas y no podrá correr()

Como ves, el concepto de abstracción es sencillo y lo utilizamos continuamente. Si no lo tuviéramos, seria mucho mas difícil comunicarnos, ya que no podríamos utilizar el concepto de clase, y deberíamos hablar de objetos concretos, no podríamos hablar de algo genérico (clase árbol), sino que tendríamos que detallar objetos concretos (encina de 1,20, pino piñonero mediterráneo, roble,…) y no quiero seguir filosofando, pero también entra la abstracción en los objetos que he comentado (tamaño, numero de ramas, color,…)

Herencia

Herencia es la facilidad para recibir atributos y comportamientos ya definidos en una clase padre, y que nos ahorra el tener que codificarlo en cada una de las especies

UML-HerenciaEn el dibujo anterior, expresamos que “arbusto” y “pino” heredan los atributos y comportamiento de la clase padre “árbol”, pero añaden cada uno un atributo distinto.

Hay veces que construiremos desde el detalle, e iremos creando abstracciones, y otras veces que nos será mas sencillo ir especializando la clase, en cualquiera de los dos casos, la herencia nos facilita el trabajo al permitir, por ejemplo, que el código de los comportamientos este en un solo sitio, y si lo tenemos que modificar, solo lo deberemos hacer en un sitio.

Ahora ya sabemos que puede haber Superclases, o clases padre (Parent class), y Subclases, o clases hijas que heredan de la Superclase. Dado que a todos los niveles, las características de una Superclase o de una Subclase son iguales, esta subclase puede, a su vez, ser Superclase de alguna otra que hereda de ella

Realmente, la herencia no seria útil si no pudiéramos sobrecargar métodos heredados, esto significa que un método definido en la Superclase, y heredado de ella, puede ser sobrescrito (reprogramado) en la subclase para que tenga el comportamiento deseado. Imaginemos esta situación:Ejemplo herencia UML

Hemos creado una “Superclase” llamada Persona, y hemos creado dos subclases que heredan de ella, Cliente y Usuario.

Cliente añade dos atributos (numeroCliente, y fechaAlta) y un comportamiento (verFechaAlta())

Usuario añade un atributo, “codigoUsuario” y un método (autorizar()). Pero nos encontramos con el problema que durante la creación del usuario debemos realizar mas acciones, por ejemplo, verificar contraseña; por lo que el método de la Superclase no nos vale. Si os fijáis, he añadido un método “crear()” en la subclase, que deberemos reescribir,  para que cumpla las especificaciones.

Encapsulación

Otra característica muy importante en la orientación a objetos, es la encapsulacion. Considerad la encapsulacion como el método para conseguir mantener juntos los datos y los comportamientos de una clase, aunque, desde mi punto de vista, su parte mas importante esta en la ocultación de los datos y la forma en que se resuelven los comportamientos

No se trata de que sean secretos, aunque puedan serlo, si no que cualquier persona que utilice nuestra clase, podrá utilizar los datos y los comportamientos SIN NECESIDAD de conocer como se han implementado esos comportamientos y/o esos datos.

Es decir, nuestra clase mantiene un control total en la forma como se van a manejar sus datos, y plena libertad para modificar la forma en que se implementan los comportamientos, solo quedando obligada a respetar el “contrato”, esto es la forma que se ha definido para su uso (nombres de métodos, tipos de parámetros….)

Voy a poner un ejemplo para demostrar las ventajas que aporta la encapsulacion.

Imaginemos que creas una clase llamada Cliente

Clase cliente

De momento, solo he indicado que la propiedad “fechaAlta” es privada, aunque para encapsular correctamente indicaríamos privadas TODAS las propiedades. Pero para nuestro ejemplo, ya vale.

Tambien he previsto un método que devuelva la fecha (verFechaAlta()). En estas condiciones, podemos considerar el atributo fechaAlta bien encapsulado. Y ¿que ventaja nos aporta?:

Imaginemos que inicialmente, la clase clientes estableció el campo fechaAlta como de tipo “Date”, pero, pasados unos meses llegamos a la conclusión que nos seria mas interesante trabajar con tres campos: día, mes, y año.

Si no hubiéramos encapsulado este atributo, deberíamos localizar todas las clases que lo estuvieran utilizando, para cambiarlas y que accedieran a los tres campos; por el contrario en nuestro desarrollo, correctamente encapsulado, como todos los demás consiguen la fecha por medio del método “verFechaAlta()”, solo será necesario modificar nuestra clase, para que ese método sepa devolver la fecha desde los tres campo…una mejora notable.

Polimorfismo

Esta extraña palabra intenta explicar la característica de los objetos  para conseguir que comportamientos semejantes se adapten al objeto de forma adecuada.

Estoy de acuerdo que el párrafo no es demasiado esclarecedor, pero el polimorfismo es algo tan intuitivo que cuesta definir; piensa en una palabra como correr, que podría ser un método de una clase que fuera vehículo.

Si heredáramos de esa clase para crear clases como bicicleta, moto, coche, avión… todos tendrían el comportamiento “correr”, pero en cada uno seria implementado de distinta forma.

Si queréis un ejemplo mas cercano, os recuerdo el diagrama que hicimos cuando se hablaba de herencia.

Ejemplo herencia UML

En la superclasePersona” creamos un comportamiento llamado “crear()”, por lo que la subclase “Cliente” lo heredo, luego, heredamos de Persona para escribir la subclase “Usuario”, pero en esa clase sobrescribimos el método “crear()” para que nos controlara usuario y contraseña.

Cuando creemos objetos basados en Cliente o en Usuario, todos ellos serán “Personas” ya que es la Superclase de ambas, pero al utilizar el método “crear()”, controlara el usuario o la contraseña según se hayan creado con “Cliente” o con “Usuario”

Eso es polimorfismo, la posibilidad que tiene un método para adaptarse al objeto que lo construyo, esa capacidad para que una llamada del tipo “Persona.crear()” se comporte de una forma u otra en función del objeto que sea.

Y en nuestro siguiente articulo, veremos como podemos diseñar una aplicacion orientada a objetos

 

Acerca de Miguel Garcia

Programador, Desarrollador web, Formador en distintas areas de informatica y director de equipos multidisciplinares.
Esta entrada fue publicada en Orientacion a objetos y etiquetada , . Guarda el enlace permanente.

Una respuesta a OOP(II)-Comprendiendo la orientación a objetos

  1. Pingback: OOP(I)- Clases y objetosRecursos para formacion

Deja un comentario