OOP non ha inventato l'incapsulamento e non è sinonimo di incapsulamento. Molti linguaggi OOP non hanno modificatori di accesso in stile C ++ / Java. Molti linguaggi non OOP hanno varie tecniche disponibili per offrire l'incapsulamento.
Un approccio classico per l'incapsulamento sono le chiusure , utilizzate nella programmazione funzionale . Questo è significativamente più vecchio di OOP ma è in qualche modo equivalente. Ad esempio in JavaScript potremmo creare un oggetto come questo:
function Adder(x) {
this.add = function add(y) {
return x + y;
}
}
var plus2 = new Adder(2);
plus2.add(7); //=> 9
L' plus2
oggetto sopra non ha alcun membro che consentirebbe l'accesso diretto a x
- è interamente incapsulato. Il add()
metodo è una chiusura sulla x
variabile.
Il linguaggio C supporta alcuni tipi di incapsulamento attraverso il meccanismo del file di intestazione , in particolare la tecnica del puntatore opaco . In C, è possibile dichiarare un nome di struttura senza definirne i membri. A quel punto nessuna variabile del tipo di quella struttura può essere usata, ma possiamo usare i puntatori a quella struttura liberamente (perché la dimensione di un puntatore alla struttura è nota al momento della compilazione). Ad esempio, considera questo file di intestazione:
#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
Ora possiamo scrivere codice che utilizza questa interfaccia di Adder, senza avere accesso ai suoi campi, ad esempio:
Adder plus2 = Adder_new(2);
if (!plus2) abort();
printf("%d\n", Adder_add(plus2, 7)); /* => 9 */
Adder_free(plus2);
E qui ci sarebbero i dettagli dell'implementazione totalmente incapsulati:
#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;
}
Esiste anche la classe di linguaggi di programmazione modulari , che si concentra su interfacce a livello di modulo. La famiglia linguistica ML incl. OCaml include un approccio interessante ai moduli chiamati funzioni . OOP ha messo in ombra la programmazione modulare ampiamente utilizzata, ma molti presunti vantaggi di OOP riguardano più la modularità che l'orientamento agli oggetti.
C'è anche l'osservazione che le classi in linguaggi OOP come C ++ o Java spesso non vengono utilizzate per oggetti (nel senso di entità che risolvono operazioni mediante associazione tardiva / invio dinamico) ma semplicemente per tipi di dati astratti (dove definiamo un'interfaccia pubblica che si nasconde dettagli di implementazione interna). Il documento On Understanding Data Abstraction, Revisited (Cook, 2009) discute questa differenza in modo più dettagliato.
Sì, molte lingue non hanno alcun meccanismo di incapsulamento. In queste lingue, i membri della struttura vengono lasciati pubblici. Al massimo, ci sarebbe una convenzione di denominazione che scoraggia l'uso. Ad esempio, penso che Pascal non avesse un meccanismo di incapsulamento utile.