OOP não inventou o encapsulamento e não é sinônimo de encapsulamento. Muitas linguagens OOP não possuem modificadores de acesso no estilo C ++ / Java. Muitas linguagens não-OOP têm várias técnicas disponíveis para oferecer encapsulamento.
Uma abordagem clássica para o encapsulamento é closures , conforme usado na programação funcional . Isso é significativamente mais antigo que o OOP, mas é de certa forma equivalente. Por exemplo. em JavaScript, podemos criar um objeto como este:
function Adder(x) {
this.add = function add(y) {
return x + y;
}
}
var plus2 = new Adder(2);
plus2.add(7); //=> 9
O objeto plus2
acima não possui um membro que permita acesso direto a x
- ele é totalmente encapsulado. O método add()
é um encerramento sobre a variável x
.
A linguagem C oferece suporte a alguns tipos de encapsulamento por meio de seu mecanismo de arquivo de cabeçalho , particularmente a técnica ponteiro opaco . Em C, é possível declarar um nome de estrutura sem definir seus membros. Nesse ponto, nenhuma variável do tipo dessa estrutura pode ser usada, mas podemos usar ponteiros para essa estrutura livremente (porque o tamanho de um ponteiro de estrutura é conhecido em tempo de compilação). Por exemplo, considere este arquivo de cabeçalho:
#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
Agora podemos escrever código que use essa interface do Adder sem ter acesso a seus campos, por exemplo:
Adder plus2 = Adder_new(2);
if (!plus2) abort();
printf("%d\n", Adder_add(plus2, 7)); /* => 9 */
Adder_free(plus2);
E aqui estariam os detalhes da implementação 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;
}
Há também a classe de linguagens de programação modulares , que enfoca o nível de módulo interfaces. A família da linguagem ML incl. OCaml inclui uma abordagem interessante para módulos chamados functors . OOP ofuscou e em grande parte substituiu a programação modular, mas muitas vantagens da OOP são mais relacionadas à modularidade do que à orientação a objetos.
Há também a observação de que classes em linguagens OOP como C ++ ou Java geralmente não são usadas para objetos (no sentido de entidades que resolvem operações através de ligação tardia / envio dinâmico), mas apenas para > tipos de dados abstratos (onde definimos uma interface pública que oculta detalhes internos de implementação). O artigo Sobre Entendendo a Abstração de Dados, Revisitado (Cook, 2009) discute essa diferença em mais detalhes.
Mas, sim, muitos idiomas não possuem nenhum mecanismo de encapsulamento. Nestes idiomas, os membros da estrutura são deixados públicos. No máximo, haveria uma convenção de nomenclatura que desencorajasse o uso. Por exemplo. Eu acho que Pascal não tinha nenhum mecanismo de encapsulamento útil.