If you're seeing this message, it means we're having trouble loading external resources on our website.

Se sei dietro un filtro web, assicurati che i domini *. kastatic.org e *. kasandbox.org siano sbloccati.

Contenuto principale

Ripasso: Programmazione Orientata agli Oggetti

Questo è un ripasso di quanto abbiamo imparato in questo tutorial sulla programmazione orientata agli oggetti.
Quando creiamo programmi, spesso scopriamo che vogliamo creare molti oggetti differenti che condividono simili proprietà - come ad esempio molti gatti che hanno il colore del pelo leggermente diverso o una dimensione leggermente diversa, con etichette e posizioni differenti. Vogliamo poter dire "questo è generalmente l'aspetto di un gatto" e poi dire "creiamo questo specifico gatto e poi quest'altro gatto, che saranno simili per certi versi ma anche diversi per altri". In quel caso, vogliamo usare la progettazione orientata agli oggetti per definire tipologie di oggetti e creare nuovi esempi di quegli oggetti.
Per definire una tipologia di oggetto in JavaScript, per prima cosa dobbiamo definire una "funzione costruttrice". Questa è la funzione che useremo ogniqualvolta vorremo creare un nuovo esempio di quella tipologia di oggetto. Ecco una funzione costruttrice per la tipologia di oggetto Libro:
var Book = function(title, author, numPages) {
  this.title = title;
  this.author = author;
  this.numPages = numPages;
  this.currentPage = 0;
};
La funzione accetta argomenti per gli aspetti che differiscono in ciascun libro: titolo, autore e numero di pagine. Poi imposta le proprietà iniziali dell'oggetto in base a questi argomenti, usando la keyword this. Quando utilizziamo this in un oggetto, ci stiamo riferendo all'istanza corrente dell'oggetto, riferendoci all'oggetto stesso. Dobbiamo salvare le proprietà in this per essere sicuri di poterle richiamare dopo.
Per creare un'istanza di un oggetto Book, dichiariamo una nuova variabile per contenerlo, poi usiamo la keyword new, seguita dal nome della funzione costruttore, e gli passiamo gli argomenti che il costruttore si aspetta:
var book = new Book("Robot Dreams", "Isaac Asimov", 320);
Possiamo quindi accedere a qualsiasi proprietà che abbiamo memorizzato nell'oggetto utilizzando la notazione puntata:
println("I loved reading " + book.title); // I loved reading Robot Dreams
println(book.author + " is my fav author"); // "Isaac Asimov" is my fav author
Lasciamo un attimo da parte questo, e vediamo cosa succederebbe se non impostassimo correttamente la nostra funzione costruttore:
var Book = function(title, author, numPages) {
};
var book = new Book("Little Brother", "Cory Doctorow", 380);
println("I loved reading " + book.title); // I loved reading undefined
println(book.author + " is my fav author"); // undefined is my favorite author
Se passiamo gli argomenti alla funzione costruttore ma non li salviamo esplicitamente in this, allora non potremo recuperarli in futuro! L'oggetto si dimenticherà di tutti gli argomenti.
Quando definiamo i tipi di oggetti, spesso vogliamo associarli alle proprietà e ai comportamenti: per esempio, tutti i nostri oggetti cat dovrebbero essere in grado di meow() e eat(). Quindi dobbiamo poter attaccare delle funzioni alle definizioni dei nostri tipi di oggetti e possiamo farlo definendoli tramite il cosiddetto object prototype:
Book.prototype.readItAll = function() {
  this.currentPage = this.numPages;
  println("You read " + this.numPages + " pages!");
};
È simile a come definiremmo normalmente una funzione, tranne per il fatto che la attacchiamo al prototipo Book invece di definirla solo globalmente. È così che JavaScript sa che questa è una funzione che può essere chiamata in ogni oggetto Book, e che questa funzione dovrebbe avere accesso al this del libro su cui è chiamata.
Possiamo quindi chiamare la funzione (che chiamiamo metodo, dato che è attaccata a un oggetto) in questo modo:
var book = new Book("Animal Farm", "George Orwell", 112);
book.readItAll(); // You read 112 pages!
Ricorda: l'obiettivo del design orientato agli oggetti è rendere più facile per noi creare più oggetti correlati (istanze di un oggetto). Vediamolo con il codice:
var pirate = new Book("Pirate Cinema", "Cory Doctorow", 384);
var giver = new Book("The Giver", "Lois Lowry", 179);
var tuck = new Book("Tuck Everlasting", "Natalie Babbit", 144);

pirate.readItAll(); // You read 384 pages!
giver.readItAll(); // You read 179 pages!
tuck.readItAll(); // You read 144 pages!
Questo codice ci dà tre libri simili: hanno tutti gli stessi tipi di proprietà e comportamenti, ma ne hanno anche di diversi. Bello!
Se pensi al mondo reale, gatti e cani sono diversi tipi di oggetti, quindi probabilmente vuoi creare diversi tipi di oggetti se vuoi programmare Gatto e Cane. Un gatto sa miagolare(), mentre un cane sa abbaiare(). Ma sono anche simili: entrambi possono mangiare(), entrambi hanno un'età, una data di nascita, e una di morte. Sono entrambi mammiferi, e questo vuol dire che hanno molto in comune, anche se sono così diversi.
In questo caso, vogliamo usare l'idea di ereditarietà degli oggetti. Un tipo di oggetto può ereditare proprietà e comportamenti da un tipo di oggetto genitore, ma poi avrà anche le sue particolarità. Ciascun Gatto e Cane eredita le caratteristiche di Mammifero, quindi non dovranno inventarsi da zero un'azione come mangiare(). Come si fa questo in JavaScript?
Torniamo al nostro esempio del libro e diciamo che Book è il tipo di oggetto "genitore", e vogliamo creare due tipi di oggetti che ereditano da esso: Paperback e EBook.
Un paperback è un libro tascabile che ha una principale differenza rispetto a un comune libro, almeno nel nostro programma: ha un'immagine di copertina. Quindi il nostro costruttore deve prendere quattro argomenti per questa informazione aggiuntiva:
var PaperBack = function(title, author, numPages, cover) {
  // ...
}
Ma non vogliamo dover fare di nuovo tutto il lavoro che abbiamo fatto nel costruttore Book per ricordare questi primi tre argomenti. Vogliamo approfittare del fatto che il codice sarebbe identico. Quindi possiamo chiamare il costruttore Book dal costruttore PaperBack e passargli questi argomenti:
var PaperBack = function(title, author, numPages, cover) {
  Book.call(this, title, author, numPages);
  // ...
};
Dobbiamo comunque salvare la proprietà cover nell'oggetto, quindi ci serve un'altra riga:
var PaperBack = function(title, author, numPages, cover) {
  Book.call(this, title, author, numPages);
  this.cover = cover;
};
Ora abbiamo un costruttore per il nostro PaperBack, che ci aiuta a condividere le stesse proprietà di Book, ma vogliamo anche che il nostro PaperBack erediti i suoi metodi. Ecco come fare, dicendo al programma che il prototipo PaperBack deve essere basato sul prototipo Book:
PaperBack.prototype = Object.create(Book.prototype);
Potremmo anche voler collegare dei comportamenti particolari solo per paperback, come poter bruciare, e possiamo farlo definendo le funzioni nel prototipo, dopo la riga qui sopra:
PaperBack.prototype.burn = function() {
  println("Omg, you burnt all " + this.numPages + " pages");
  this.numPages = 0;
};
E ora possiamo creare un nuovo libro paperback, leggerlo tutto e bruciarlo!
var calvin = new PaperBack("The Essential Calvin & Hobbes", "Bill Watterson", 256, "http://ecx.images-amazon.com/images/I/61M41hxr0zL.jpg");

calvin.readItAll(); // You read 256 pages!
calvin.burn(); // Omg, you burnt all 256 pages!
(Beh, non lo bruceremo davvero, perché è un libro fantastico, ma forse lo faremmo se fossimo bloccati in un deserto di ghiaccio e volessimo disperatamente un modo per scaldarci per non morire.)
E ora sai come possiamo usare i principi di progettazione orientata agli oggetti in JavaScript per creare dati più complessi per i tuoi programmi e strutturare meglio il mondo dei tuoi programmi.

Vuoi unirti alla conversazione?

Capisci l'inglese? Clicca qui per vedere più discussioni che avvengono sul sito inglese di Khan Academy.