Vai al contenuto principale
StoriaStoria dell’informaticaPrincipiante

Programmazione orientata agli oggetti: oggetti, messaggi e astrazioni riutilizzabili

Da Simula e Smalltalk alle classi e ai prototipi moderni: oggetti, messaggi, incapsulamento, polimorfismo e limiti dell'ereditarietà.

Pubblicato 10 agosto 2026Aggiornato 15 settembre 2026Lettura : 7 minDi Yann Bastien
Programmazione orientata agli oggetti con oggetti, messaggi e astrazioni riutilizzabili
Mostra indice
  1. Prima degli oggetti
  2. Simula: rappresentare gli attori
  3. Classe, oggetto e la visione di Alan Kay
  4. Smalltalk: tutto diventa oggetto
  5. Stato, identità e comportamento
  6. Incapsulamento e astrazione
  7. Ereditarietà e polimorfismo
  8. C++ e Objective-C
  9. Gli anni Novanta: l’OOP diventa dominante
  10. Java, C# e diffusione industriale
  11. Python e JavaScript
  12. Composizione invece di ereditarietà
  13. Interfacce, SOLID e principi di progettazione
  14. Pattern, UML e strumenti
  15. Test e limiti delle astrazioni
  16. Critiche e altri paradigmi
  17. GUI, giochi e sistemi distribuiti
  18. Che cosa resta davvero dell’OOP?
  19. Perché imparare ancora l’OOP?
  20. Da ricordare
  21. Domande frequenti
  22. Che cos’è la programmazione orientata agli oggetti?
  23. Chi ha inventato l’OOP?
  24. Qual è la differenza tra classe e oggetto?
  25. Quali sono i principi principali?
  26. L’ereditarietà è obbligatoria?
  27. JavaScript è orientato agli oggetti?
  28. Python è orientato agli oggetti?
  29. L’OOP è superata?
  30. Composizione o ereditarietà?
  31. Perché l’OOP è ancora importante?

La programmazione orientata agli oggetti (OOP) è oggi così familiare che è facile dimenticarne l’evoluzione storica. Classi, oggetti, metodi, ereditarietà, interfacce e polimorfismo non nacquero insieme né come ricetta universale.

L’orientamento agli oggetti nasce da una domanda pratica: come rappresentare entità dotate di stato, comportamento e interazioni con altre entità? Da Simula a Smalltalk, poi C++, Java, Python e JavaScript, le risposte cambiarono profondamente.

Prima degli oggetti

I linguaggi di alto livello degli anni Cinquanta e Sessanta introdussero funzioni, procedure, strutture dati e moduli. Con sistemi sempre più grandi, modificare dati manipolati da funzioni sparse diventava costoso. Una delle risposte più influenti arrivò dalla simulazione.

Simula: rappresentare gli attori

Negli anni Sessanta gli informatici norvegesi Ole-Johan Dahl e Kristen Nygaard svilupparono linguaggi di simulazione. Con Simula 67 introdussero meccanismi fondamentali: classi, oggetti, ereditarietà e metodi virtuali. Una classe descrive una categoria; un oggetto ne rappresenta un’istanza concreta.

Classe, oggetto e la visione di Alan Kay

Nel modello classico, una classe definisce struttura e comportamenti comuni e un oggetto è un’istanza con stato proprio. Il modello è centrale in C++, Java e C#, ma non universale: esistono sistemi basati sui prototipi.

Tra la fine degli anni Sessanta e l’inizio dei Settanta, Alan Kay sviluppò un’altra visione, approfondita nella nostra biografia di Alan Kay: l’idea essenziale erano oggetti autonomi che si scambiano messaggi, non le gerarchie di classi.

Smalltalk: tutto diventa oggetto

Al Xerox PARC, Alan Kay, Dan Ingalls, Adele Goldberg e altri svilupparono Smalltalk. Numeri, collezioni e classi partecipano al modello a oggetti e l’interazione ruota attorno ai messaggi. L’ambiente interattivo influenzò profondamente personal computing e IDE.

Stato, identità e comportamento

Un oggetto combina normalmente stato, comportamento e identità. Due conti bancari possono avere lo stesso saldo senza essere lo stesso conto. In alcuni domini l’identità è fondamentale; in altri valori immutabili e funzioni sono più adatti. L’OOP è quindi uno strumento, non un obbligo universale.

Incapsulamento e astrazione

L’incapsulamento riunisce stato e operazioni e limita l’accesso ai dettagli interni. Il suo scopo è ridurre le dipendenze e permettere a un’astrazione di cambiare senza rompere chi la utilizza.

L’astrazione mostra ciò che un componente sa fare senza esporne l’implementazione. L’OOP non ha inventato l’astrazione, ma ne ha diffuso una forma centrata su entità che combinano stato e comportamento.

Ereditarietà e polimorfismo

L’ereditarietà permette a una classe di acquisire e specializzare caratteristiche di un’altra. Può riutilizzare codice, ma crea anche accoppiamento e gerarchie rigide. Oggi è considerata uno strumento tra molti.

Il polimorfismo permette allo stesso codice di lavorare con oggetti diversi attraverso un comportamento comune. Può basarsi su ereditarietà, interfacce, protocolli, duck typing o generics. L’idea centrale è programmare verso un contratto e non verso un’implementazione concreta.

C++ e Objective-C

Dal 1979 Bjarne Stroustrup combinò idee di Simula con l’efficienza di C. Il progetto divenne C++, che diffuse l’OOP nell’industria senza abbandonare altri paradigmi.

Objective-C, creato da Brad Cox e Tom Love, seguì una strada diversa: uno strato dinamico sopra C ispirato ai messaggi di Smalltalk. Divenne importante in NeXT e Apple prima di Swift.

Gli anni Novanta: l’OOP diventa dominante

Negli anni Novanta interfacce grafiche, design pattern e UML contribuirono alla diffusione dell’OOP. Fu talvolta presentata come un metodo generale per progettare qualunque sistema, producendo pratiche durature ma anche eccessi.

Java, C# e diffusione industriale

Java arrivò nel 1995 con classi, garbage collection e interfacce. La nostra storia di Java e la biografia di James Gosling approfondiscono questa evoluzione.

C# riprese poi molte idee familiari in .NET e si evolse con generics, lambda, LINQ, record e pattern matching. Anche i linguaggi fortemente associati all’OOP sono diventati multiparadigma.

Python e JavaScript

Python supporta classi e polimorfismo senza imporli ovunque. Il duck typing privilegia spesso i comportamenti disponibili rispetto a una gerarchia precisa.

JavaScript, creato da Brendan Eich, si basa storicamente sui prototipi. La moderna sintassi class continua a poggiare su questo meccanismo.

Composizione invece di ereditarietà

Con l’esperienza si è diffuso il consiglio preferire la composizione all’ereditarietà. La composizione riduce spesso l’accoppiamento e facilita la sostituzione dei componenti. Non rende inutile l’ereditarietà, ma evita di trasformare ogni riuso in un albero di classi.

Interfacce, SOLID e principi di progettazione

Le interfacce separano ciò di cui un componente ha bisogno dall’implementazione concreta. Questa idea è alla base della dependency injection e di diversi principi SOLID.

SOLID è un insieme di euristiche, non di leggi. Un’applicazione meccanica può moltiplicare classi, interfacce e livelli senza vantaggi. Un’astrazione è utile quando rappresenta un vero confine di responsabilità o variazione.

Pattern, UML e strumenti

Nel 1994 Design Patterns rese popolari pattern come Factory, Observer, Strategy, Decorator e Adapter. Il loro valore principale è offrire un vocabolario condiviso, non ricette obbligatorie.

UML unificò diversi metodi di modellazione e i diagrammi delle classi divennero strettamente associati all’OOP. Pattern e diagrammi aiutano a ragionare, ma non sostituiscono un design adatto al problema.

Test e limiti delle astrazioni

Incapsulamento, interfacce e dependency injection possono facilitare i test attraverso fake, stub o mock. Ma frammentare un’architettura solo per agevolare il mocking può peggiorarla. Più astrazioni non significano automaticamente design migliore.

Critiche e altri paradigmi

Con il predominio dell’OOP emersero limiti: gerarchie profonde e fragili, stato mutabile condiviso, oggetti troppo interconnessi e architetture “enterprise” sovraccariche di livelli e factory.

La programmazione funzionale ha riportato in primo piano funzioni pure e dati immutabili. Oggi Java, C#, C++, Python e JavaScript combinano approcci diversi. L’opposizione «oggetti contro funzionale» è quindi sempre meno utile.

GUI, giochi e sistemi distribuiti

Interfacce grafiche e giochi si prestano ancora bene a entità con stato e identità, ma i motori moderni usano anche Entity Component System (ECS) che privilegiano composizione e separazione dei dati.

Nei sistemi distribuiti, il modello ad attori organizza entità che ricevono messaggi e mantengono il proprio stato. Non è OOP classica, ma ricorda l’importanza attribuita da Alan Kay a messaggi e isolamento.

Che cosa resta davvero dell’OOP?

Dopo decenni, incapsulamento, polimorfismo, composizione, identità e stato restano idee particolarmente durature. La grande gerarchia di classi ha invece perso influenza.

Smalltalk, C++, Java, Python e JavaScript mostrano che l’OOP è meglio compresa come una famiglia di modelli di programmazione che come una checklist assoluta.

Perché imparare ancora l’OOP?

Una quantità enorme di software e framework usa classi e oggetti. Comprendere incapsulamento, responsabilità, contratti e polimorfismo rimane utile. La maturità consiste meno nel «mettere oggetti ovunque» che nello scegliere la rappresentazione adatta al problema.

Da ricordare

L’OOP nasce progressivamente con Simula, cambia con Smalltalk e Alan Kay, si diffonde industrialmente con C++ e diventa dominante con Java. Python e JavaScript mostrano modelli più dinamici e multiparadigma.

L’esperienza ha corretto alcuni eccessi: l’ereditarietà non è più la risposta naturale a ogni riuso, mentre composizione, interfacce, immutabilità e funzioni hanno acquisito importanza.

La lezione più duratura non è «tutto deve essere una classe», ma raggruppare responsabilità coerenti, nascondere dettagli inutili e permettere ai componenti di collaborare senza dipendere eccessivamente dalle implementazioni interne.

Domande frequenti

Che cos’è la programmazione orientata agli oggetti?

È una famiglia di approcci che organizza il software attorno a oggetti con stato, identità e comportamento che collaborano tramite metodi, messaggi o interfacce.

Chi ha inventato l’OOP?

Non esiste un unico inventore. Dahl e Nygaard introdussero meccanismi fondamentali in Simula; Alan Kay e il team Smalltalk svilupparono poi una visione centrata sui messaggi.

Qual è la differenza tra classe e oggetto?

Una classe descrive struttura e comportamenti comuni; un oggetto è un’istanza particolare con stato proprio. I sistemi a prototipi funzionano diversamente.

Quali sono i principi principali?

Incapsulamento, astrazione, ereditarietà e polimorfismo; nella pratica moderna anche composizione, interfacce e gestione delle dipendenze.

L’ereditarietà è obbligatoria?

No. Molti sistemi preferiscono composizione o interfacce.

JavaScript è orientato agli oggetti?

Sì, ma storicamente tramite prototipi. Anche la sintassi class moderna si basa su di essi.

Python è orientato agli oggetti?

Sì, ma è multiparadigma e non obbliga a organizzare tutto in classi.

L’OOP è superata?

No. È ancora molto usata, ma non viene più considerata una soluzione universale.

Composizione o ereditarietà?

Spesso la composizione produce componenti più flessibili e meno accoppiati. L’ereditarietà resta utile quando esiste una vera specializzazione.

Perché l’OOP è ancora importante?

Perché incapsulamento, responsabilità, contratti e polimorfismo aiutano ancora a gestire la complessità nelle architetture multiparadigma.

Questo articolo ti è stato utile?

Fonti e riferimenti

  1. 1.ACM - The Early History of Smalltalk
  2. 2.Computer History Museum - The Birth of the Object-Oriented Language Simula
  3. 3.Bjarne Stroustrup - A History of C++

Raccolta

Linguaggi di programmazione

10 / 26

  1. 01Grace Hopper: dai primi compilatori a COBOL
  2. 02John Backus: FORTRAN, la notazione BNF e il rifiuto del codice macchina
  3. 03Dennis Ritchie: il linguaggio C al cuore di Unix
  4. 04FORTRAN: dimostrare che un compilatore può competere con l'assembly
  5. 05Il linguaggio C: rendere portabili i sistemi senza nascondere la macchina
  6. 06Niklaus Wirth: da Pascal a Oberon, progettare con la semplicità
  7. 07Bjarne Stroustrup: progettare C++ senza rinunciare alle prestazioni
  8. 08Pascal: imparare a programmare rendendo visibile la struttura
  9. 09C++: da C with Classes al C++ moderno
  10. 10Programmazione orientata agli oggetti: oggetti, messaggi e astrazioni riutilizzabili
  11. 11Guido van Rossum: creare Python per rendere il codice leggibile
  12. 12Brendan Eich: JavaScript, dal prototipo Netscape allo standard del Web
  13. 13James Gosling: l'ingegnere all'origine di Java
  14. 14Python: leggibilità, batterie incluse e un ecosistema globale
  15. 15Java: scrivere una volta, eseguire ovunque
  16. 16JavaScript: il linguaggio che ha reso interattivo il Web
  17. 17Ken Thompson: da Unix a Go, la semplicità come metodo
  18. 18John McCarthy: Lisp e l'idea di programmare con i simboli
  19. 19Alan Kay: Smalltalk e il computer come medium personale
  20. 20Barbara Liskov: l'astrazione che ha reso modulare il software
  21. 21Robin Milner: ML, dimostrazione assistita e linguaggi dell'interazione
  22. 22Brian Kernighan: AWK, Unix e l'arte di spiegare il codice
  23. 23Anders Hejlsberg: da Turbo Pascal a C# e TypeScript
  24. 24Larry Wall: Perl, il linguaggio che ha collegato gli strumenti di Internet
  25. 25Yukihiro Matsumoto: Ruby e la felicità del programmatore
  26. 26Rasmus Lerdorf: PHP e la democratizzazione del Web dinamico
BiografiaStoria dell’informaticaPrincipiante

James Gosling: l'ingegnere all'origine di Java

Come James Gosling e il team Green di Sun progettarono Java: da Oak alle macchine virtuali e alla promessa della portabilità.

17 agosto 20265 min