OOP no inventó la encapsulación y no es sinónimo de encapsulación. Muchos lenguajes OOP no tienen modificadores de acceso de estilo C ++ / Java. Muchos lenguajes que no son OOP tienen varias técnicas disponibles para ofrecer encapsulación.
Un enfoque clásico para la encapsulación es el cierre , como se usa en la programación funcional . Esto es significativamente más antiguo que OOP pero es de alguna manera equivalente. Por ejemplo, en JavaScript podríamos crear un objeto como este:
function Adder(x) {
this.add = function add(y) {
return x + y;
}
}
var plus2 = new Adder(2);
plus2.add(7); //=> 9
El plus2
objeto anterior no tiene ningún miembro que permita el acceso directo x
, está completamente encapsulado. El add()
método es un cierre sobre la x
variable.
El lenguaje C admite algunos tipos de encapsulación a través de su mecanismo de archivo de encabezado , particularmente la técnica de puntero opaco . En C, es posible declarar un nombre de estructura sin definir sus miembros. En ese momento, no se puede usar ninguna variable del tipo de esa estructura, pero podemos usar punteros a esa estructura libremente (porque el tamaño de un puntero de estructura se conoce en tiempo de compilación). Por ejemplo, considere este archivo de encabezado:
#ifndef ADDER_H
#define ADDER_H
typedef struct AdderImpl *Adder;
Adder Adder_new(int x);
void Adder_free(Adder self);
int Adder_add(Adder self, int y);
#endif
Ahora podemos escribir código que use esta interfaz Adder, sin tener acceso a sus campos, por ejemplo:
Adder plus2 = Adder_new(2);
if (!plus2) abort();
printf("%d\n", Adder_add(plus2, 7)); /* => 9 */
Adder_free(plus2);
Y aquí estarían los detalles de implementación totalmente encapsulados:
#include "adder.h"
struct AdderImpl { int x; };
Adder Adder_new(int x) {
Adder self = malloc(sizeof *self);
if (!self) return NULL;
self->x = x;
return self;
}
void Adder_free(Adder self) {
free(self);
}
int Adder_add(Adder self, int y) {
return self->x + y;
}
También existe la clase de lenguajes de programación modulares , que se centra en las interfaces de nivel de módulo. La familia de idiomas ML incl. OCaml incluye un enfoque interesante para los módulos llamados functores . OOP eclipsó y moduló en gran medida la programación modular, sin embargo, muchas de las supuestas ventajas de OOP tienen más que ver con la modularidad que con la orientación a objetos.
También se observa que las clases en lenguajes OOP como C ++ o Java a menudo no se usan para objetos (en el sentido de entidades que resuelven operaciones mediante un enlace tardío / despacho dinámico), sino simplemente para tipos de datos abstractos (donde definimos una interfaz pública que oculta detalles de implementación interna). El documento Sobre la comprensión de la abstracción de datos, revisado (Cook, 2009) analiza esta diferencia con más detalle.
Pero sí, muchos idiomas no tienen ningún mecanismo de encapsulación. En estos idiomas, los miembros de la estructura se dejan públicos. A lo sumo, habría una convención de nomenclatura para desalentar el uso. Por ejemplo, creo que Pascal no tenía un mecanismo de encapsulación útil.