gravatar

Conceptos básicos de la POO - Parte 4



Encapsulamiento

El término encapsulamiento suele utilizarse de forma ambigua para referir a cosas diferentes: las clases como "mecanismo" de agrupación de comportamiento y atributos, "mecanismos" de restricción del acceso a métodos y variables, y al ocultamiento de información como principio de diseño orientado a objetos.

De acuerdo al primer significado el encapsulamiento refleja el hecho de que los objetos son entidades que agrupan los atributos y métodos que operan sobre ellos. Literalmente un objeto es una cápsula, mientras que su interfaz se puede ver como sus puntos de contacto con el exterior.

En la mayoría de los lenguajes orientados a objetos, Gambas incluido, la declaración de una clase de objetos garantiza esta acepción de encapsulamiento. En realidad, este concepto así definido es parte del concepto mismo de objeto. Sin embargo, esto no garantiza de ningún modo el ocultamiento de información.

El segundo significado, refiere al control que un lenguaje permite sobre el acceso a los miembros de un objeto. Se trata ni más ni menos que del nivel de visibilidad de los miembros que en lenguajes como Gambas, Java y otros, queda determinado por la especificación de las palabras claves PUBLIC y PRIVATE en la declaración de los métodos y variables. Estas palabras claves, frecuentemente denominadas especificadores de acceso, definen qué miembros forman parte de la interfaz y cuáles son parte de la implementación.

El tercer significado iguala al término encapsulamiento con el término ocultamiento de información. Utilizar estos términos como sinónimos es correcto, pero puede resultar confuso si se mezcla su significado con los dos primeros o si se cae en la creencia de que los "mecanismos" de encapsulamiento de los lenguajes pueden garantizar la ocultación de la información.

Para poder establecer diferencias cuando sea necesario, este libro toma como convención distintos significados para los términos encapsulamiento, accesibilidad y ocultamiento de información. Es decir que:

  • El encapsulamiento es la propiedad de un objeto de agrupar sus métodos y atributos.
  • La accesibilidad o visibilidad es la propiedad de los métodos y atributos que define si pertenecen al interfaz o a la implementación, es decir, si son accesibles desde el exterior o no.
  • El ocultamiento de información es un principio del diseño orientado a objetos que sugiere como condición necesaria para obtener un buen diseño que éste debe garantizar que todos los detalles de la implementación permanezcan ocultos hacia el exterior.

Pero cuando se mencione el término "encapsulamiento" sin más, se estará haciendo referencia a las tres definiciones como un todo.

El concepto de ocultamiento de información no es propio de la programación orientada a objetos ya que esto es exactamente lo que ocurre en el paradigma de programación modular y estructurada cuando se escriben rutinas y módulos.

Veamos un típico procedimiento escrito en Gambas siguiendo el estilo de programación modular y estructurada:

SUB swap(byref a AS Integer, byref b AS Integer) DIM c AS Integer c = a a = b b = c END

De este ejemplo se puede fácilmente deducir que el procedimiento swap:

  • Encapsula comportamiento y un atributo en su interior.
  • Oculta parcialmente su implementación, incluyendo a su variable local c.
  • Posee una interfaz de comunicación con el exterior conformada por su firma (su nombre y su lista de parámetros).
  • El uso de los parámetros formales dentro de la función y la visibilidad de sus tipos de datos (Integer) rompe parcialmente el ocultamiento de información y define una limitación del procedimiento: sólo puede intercambiar valores enteros.

Las diferencias más obvias con la programación orientada a objetos es que ésta lleva estos conceptos a niveles más altos, que una clase dispone de "mecanismos" que no existen en el paradigma modular y estructurado para las funciones y procedimientos, y que la POO requiere de la aplicación de éstos y otros conceptos como principios de diseño.

Utilizaremos el siguiente ejemplo para puntualizar algunas cosas:

'Parte de la definición de la clase Perro PRIVATE $nombre AS String PRIVATE $raza AS String PRIVATE $propietario AS String PUBLIC SUB _new(nombre AS String, raza AS String, propietario AS String) $nombre = nombre $raza = raza $propietario = propietario END PUBLIC SUB ladrar() AS String RETURN "Guau" END ... 'Un objeto que usa un objeto Perro PRIVATE fido AS Perro ... fido = new Perro("Fido", "Fox Terrier", "José Fidux") ... fido.ladrar()

Observe que en la definición de la clase Perro, las variables son privadas y el método ladrar() es público. Los modificadores de acceso PRIVATE y PUBLIC definen que el método ladrar() sea parte de la interfaz de los objetos Perro y que, en cambio, las variables sean parte de la implementación. En este ejemplo, dicho mecanismo resulta suficiente para asegurar una clara separación entre interfaz e implementación, es decir, para asegurar el ocultamiento de información.

Note también que el acceso a los miembros públicos de un objeto se realiza mediante la notación objeto punto miembro. No es posible acceder directamente a los miembros públicos de un objeto sin hacer referencia explícita a ese objeto y es imposible acceder a los miembros privados.

La programación orientada a objetos se sirve del encapsulamiento (en las tres acepciones que se mencionaron antes) para permitir una clara separación entre la interfaz de una clase y su implementación.

Esta noción es fundamental ya que le permite al programador utilizar los objetos conociendo únicamente su interfaz, es decir, abstrayéndolo de los detalles de la implementación. Así, resulta posible modificar las clases sin que ello produzca efectos secundarios en el resto del programa, mientras se respete su interfaz. Esta es una de las aplicaciones del concepto de abstracción en la POO.

Si a esta altura se está preguntando ¿para qué sirve el encapsulamiento? La respuesta es:

  • Para que el programador que usa una clase para crear objetos únicamente pueda usarlos a través de su interfaz y así evitar un mal uso de esos objetos.
  • Para simplificar el uso de los objetos, de modo que el programador que los crea sólo debe conocer la interfaz.
  • Para que sea posible cambiar la implementación de una clase, sin que ello afecte el comportamiento de los objetos que se crean a partir de ella.

Más adelante se profundizarán y ejemplificarán con amplitud estos conceptos.

Los comentarios están habilitados para que los lectores puedan participar en la corrección del libro, realizar preguntas puntuales o sugerencias. Todo comentario fuera de estos objetivos será eliminado. Por favor, tenga en cuenta lo siguiente:

- Cumpla las normas de etiqueta.

- Realice críticas constructivas.

- No sea redundante.