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 idiomas que no son OOP tienen varias técnicas disponibles para ofrecer encapsulación.
Un enfoque clásico para la encapsulación es cierres , como se usa en programación funcional . Esto es significativamente más antiguo que el OOP, pero es de una manera equivalente. P.ej. 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 objeto plus2
anterior no tiene ningún miembro que permita el acceso directo a x
; está completamente encapsulado. El método add()
es un cierre sobre la variable x
.
El lenguaje C admite algunos tipos de encapsulación a través de su 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 los punteros a esa estructura libremente (porque el tamaño de un puntero de estructura se conoce en el momento de la 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 de 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í están los detalles de la 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 modular , que se centra en el nivel de módulo interfaces La familia del lenguaje ML incl. OCaml incluye un enfoque interesante para los módulos llamados functors . La programación orientada a objetos (OOP, por sus siglas en inglés) ha ensombrecido y en gran parte la programación modular, aunque muchas de las supuestas ventajas de la POO se refieren más a la modularidad que a 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 a través del enlace tardío / envío dinámico) sino simplemente para tipos de datos abstractos (donde definimos una interfaz pública que oculta los detalles de la 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 desalentadora de uso. P.ej. Creo que Pascal no tenía un mecanismo de encapsulación útil.