Programmazione orientata agli oggetti con JavaScript

Cosa starai creando

Conosce il termine "codice spaghetti"? Questa è una metafora che potresti sentire dagli sviluppatori non JavaScript nella critica della lingua. È un codice senza struttura. Consisterà di riga dopo riga di dichiarazioni. Alcuni potrebbero essere avvolti in funzioni, altri no. E se sei fortunato, tutte le 9000 linee di codice saranno in un unico file. Questa struttura "spaghetti" è probabilmente il risultato di una programmazione procedurale.

Nella programmazione procedurale, le funzioni vengono utilizzate per eseguire attività. Abbiamo bisogno di funzioni, ma abbiamo anche bisogno di un progetto con cui possiamo lavorare. E mentre gli spaghetti sono ottimi per la cena, non è per il codice. L'antidoto è una programmazione orientata agli oggetti. Per comprendere la programmazione orientata agli oggetti, tratteremo la progettazione di un programma, la definizione di classi e la creazione di oggetti.

Progettare un programma

Immaginiamo che ti sia stato assegnato il compito di creare un'applicazione per una libreria. Solo per divertimento, chiamiamo la nostra libreria Amazzonia. L'Amazzonia avrà libri. Ci saranno recensioni per i libri. E vorremmo cercare libri per autore. Ci saranno più funzionalità che vorremmo implementare nella nostra app, ma per ora è sufficiente.  

La programmazione orientata agli oggetti è incentrata sulla creazione di oggetti. Quindi, come possiamo tradurre questi requisiti in oggetti? Una tecnica è quella di fare una lista dei nomi dalla nostra descrizione e quindi affinare la lista a quelli rilevanti per il problema. Abbiamo menzionato i seguenti nomi nel nostro problema:

  • Applicazione
  • Libreria
  • Libri
  • Recensioni
  • Autore

L'applicazione è un nome irrilevante, quindi può essere scartato. Possiamo anche sbarazzarci della libreria perché è simile all'applicazione. Se avessimo bisogno di fare qualcosa con più librerie, potremmo tenerlo. Siamo rimasti con libri, recensioni e autori. (Gli autori sono stati pluralizzati perché avremo più autori in questa applicazione.)

Ora diamo un'occhiata a come progetteremo ogni classe. Una classe è un progetto per la creazione di oggetti. La classe di libri che creiamo ci fornirà un progetto per la creazione di oggetti di libri. 

È simile a come un architetto utilizza un progetto per creare case. Il progetto mostrerà le camere da letto, i bagni, la cucina e il soggiorno. Molte case possono essere fatte da questo progetto. Tuttavia, non tutti devono essere uguali. Ogni casa può essere personalizzata cambiando la vernice, la pavimentazione o gli infissi, ad esempio.

Compito

Scrivi le classi che useresti per un programma di carrello della spesa. Il carrello della spesa dovrebbe essere in grado di fare quanto segue: 

  1. Mantieni un elenco di elementi.
  2. Aggiungi e rimuovi gli oggetti dal carrello.
  3. Calcola il totale del carrello.
  4. Ottieni informazioni sui clienti.
  5. Crea una ricevuta per gli acquisti.

Classi

Per progettare la nostra classe di libri, dobbiamo considerare ciò che la classe è responsabile della conoscenza e di ciò che è responsabile del fare. Per un libro, dobbiamo conoscere il titolo, l'autore e il codice ISBN. Questi sono i nostri attributi dei dati. 

Alcune cose che la classe dovrà essere in grado di fare sono ottenere e impostare il titolo, ottenere e impostare l'autore, e ottenere e impostare il codice ISBN. Questi saranno i metodi della classe. Ecco come dovrebbe apparire la nostra classe di libri, date le nostre esigenze:

class Book costruttore (titolo, autore, isbn) this.title = titolo; this.author = autore; questo.isbn = isbn;  getTitle () return this.title;  setTitle (newTitle) this.title = newTitle;  getAuthor () return this.author;  setAuthor (newAuthor) this.author = newAuthor;  getIsbn () return this.isbn;  setIsbn (newIsbn) this.isbn = newIsbn;  

Per convenzione, il nome della classe è in maiuscolo. Il costruttore è una funzione speciale che dichiara e inizializza gli attributi dei dati. All'interno della funzione di costruzione, gli attributi vengono aggiunti utilizzando il Questo parola chiave. Successivamente, tutti i metodi della classe sono elencati senza separatori.  

Metodi che iniziano con ottenere sono noti come metodi di accesso perché restituiscono un valore. Metodi che iniziano con impostato sono metodi mutator perché memorizzano un valore o modificano il valore di un attributo.  

Questa è la forma generale per la definizione di una classe:

class ClassName constructor (... args) this.attr = arg1; this.attr2 = arg2; ... methodOne () ... methodTwo () ...

Una classe può anche essere dichiarata usando questa sintassi:

const ClassName = class ...

Le classi possono anche avere metodi statici. Un metodo statico è un metodo che è una proprietà della classe, non dell'oggetto. Diciamo che vogliamo creare un metodo statico per la nostra classe di libri per generare id. Questa è la sintassi:

class Book costruttore () ... static generateId () ... 

Per chiamare il metodo:

Book.generateId ();

Una domanda naturale sarebbe quando e perché dovresti usare un metodo statico? Non posso dire di conoscere una buona ragione per usare metodi statici. Dipende da come progetta la tua classe. Un metodo statico potrebbe essere utilizzato come metodo di supporto per gli oggetti, ma tali funzioni potrebbero essere memorizzate nella loro classe. Se conosci un buon caso d'uso, lascia i tuoi pensieri nei commenti.

Infine, per l'organizzazione, dovresti memorizzare una classe come modulo. Un modulo è solo un file che contiene il tuo codice. Per rendere la nostra classe di libri in un modulo, aggiungiamo un esportare dichiarazione prima di questo.

export class Book ...

Per usare la classe Book in un altro file, la importiamo.

importare Libro dal libro

Dove il contiene i valori che sono stati esportati dal modulo e dal libro è un riferimento al file Book.js.

Compito

Definire una classe per autori e recensioni.  

Oggetti

La classe da sola è inutile per noi a meno che non facciamo qualcosa con essa. Vogliamo creare libri. Per fare ciò, dobbiamo istanziare la classe. Instantiate è il termine tecnico per la creazione di nuovi oggetti. Chiamiamo l'oggetto creato dalla classe un'istanza. Ecco come creeremmo una nuova istanza di un libro:

let book = new Book ("Great Expectations", "Charles Dickens", 1234); book.getTitle () // Grandi aspettative

Gli oggetti devono essere istanziati con il nuovo operatore. I dati passati nell'oggetto sono i parametri che abbiamo definito nel nostro costruttore. Questa è la forma generale per creare un'istanza di una classe:

variableName = new ClassName (... args);

Supponiamo di voler aggiungere attributi alla nostra classe di libri come un ID, il prezzo e il numero in magazzino. Ora abbiamo sei parametri nel nostro costruttore, e questo non è carino. Non è solo male da guardare. Crea uno sforzo extra per gli sviluppatori che usano la classe perché devono conoscere l'ordine degli argomenti. Una soluzione migliore è passare un oggetto come argomento. Esempio:

class Book costruttore (dati) this.id = data.id; this.title = data.title; this.author = data.author; this.isbn = data.isbn; this.units = data.units; this.price = data.price;  getTitle () return this.title;  ...

Per istanziare l'oggetto:

let data = id: 1, titolo: "Great Expectations", autore: "Charles Dickens", isbn: 1234, unità: 10, prezzo: 29,95 let book = new Book (data);

Nel nostro esempio, avremmo potuto accedere anche al titolo con la dichiarazione titolo del libro perché tutti gli attributi nella classe sono pubblici. Ora ti starai chiedendo perché ho creato tutti questi metodi se siamo in grado di accedere direttamente agli attributi. È stato solo per mostrarti la sintassi? Sì. Inoltre, voglio mostrare i vantaggi di organizzare il tuo codice in questo modo. 

Il raggruppamento del codice correlato in un oggetto è noto come incapsulamento. Uno dei vantaggi dell'incapsulamento è l'occultamento dei dati. Nascondersi dei dati significa che non è possibile accedere agli attributi di un oggetto al di fuori della classe. 

In altri linguaggi come Java e Python, possiamo avere attributi privati ​​e metodi privati. Poiché tutti i nostri dati sono pubblici per impostazione predefinita in una classe JavaScript, non possiamo sfruttare questa funzione. Tuttavia, dovremmo accedere ai nostri dati con getter e setter. Una convenzione consiste nel prefisso di un attributo con un carattere di sottolineatura _ per segnalare che è privato.

Compito

Crea un oggetto libro che utilizza un oggetto autore per impostare l'attributo autore.  

Pensieri finali

Abbiamo appreso che una classe è un progetto per la creazione di oggetti e un oggetto è un'istanza di una classe. Il vantaggio di creare software in oggetti è che fornisce una struttura del programma e lo rende più gestibile. 

Quando abbiamo un programma di grandi dimensioni, suddividerlo in oggetti consente di sviluppare e mantenere le parti indipendentemente dalle altre parti. Con questa modularità arriva la riusabilità. Poiché il nostro codice è incapsulato, gli oggetti possono essere utilizzati più e più volte in altre parti del programma. Inoltre abbiamo un'unità di codice testabile. Il test migliore è il nostro codice, più sicuro è dai bug.  

Ulteriori letture

  • Mozilla Developer Network - Classi
  • Non sai JS: ES6 e oltre: Capitolo 3 Organizzazione
  • Esplorando ES6: Classi