9.1 Concetti base
Incapsulamento — è uno dei concetti chiave della programmazione orientata agli oggetti (OOP), che permette di nascondere i dettagli interni dell'implementazione di un oggetto e di fornire accesso a questi dettagli attraverso interfacce ben definite. Questo aiuta a migliorare la sicurezza e semplifica la gestione del codice.
Vantaggi dell'incapsulamento:
- Nascodere i dati: l'incapsulamento permette di nascondere i dettagli interni dell'implementazione e di fornire accesso solo ai metodi e proprietà necessari. Questo previene l'uso scorretto degli oggetti e migliora la sicurezza del codice.
- Controllo dell'accesso: l'incapsulamento permette di controllare l'accesso ai dati e metodi, fornendo la possibilità di modificare lo stato interno di un oggetto solo attraverso metodi specifici.
- Mantenibilità: l'incapsulamento migliora la supportabilità del codice, poiché i cambiamenti nell'implementazione non influenzano l'interfaccia esterna di una classe. Questo permette di apportare modifiche all'implementazione senza modificare il codice che utilizza la classe.
- Miglioramento del testing: l'incapsulamento permette di isolare l'implementazione interna di un oggetto, il che semplifica il test unitario e riduce la probabilità di effetti collaterali.
In JavaScript l'incapsulamento si realizza utilizzando metodi e proprietà, e a partire da ES2022, sono disponibili anche campi e metodi privati.
9.2 Incapsulamento tramite closure
Prima dell'introduzione dei campi privati in ES2022, l'incapsulamento in JavaScript era spesso raggiunto utilizzando le closure.
Esempio:
- La variabile
count
è accessibile solo all'interno della funzionecreateCounter
e non è accessibile dall'esterno - I metodi
increment
,decrement
egetCount
possono interagire con la variabile privatacount
function createCounter() {
let count = 0; // variabile privata
return {
increment() {
count++;
console.log(count);
},
decrement() {
count--;
console.log(count);
},
getCount() {
return count;
}
};
}
const counter = createCounter();
counter.increment(); // 1
counter.increment(); // 2
console.log(counter.getCount()); // 2
counter.decrement(); // 1
9.3 Campi privati in ES2022
In ES2022 sono stati introdotti campi e metodi privati, che si dichiarano utilizzando il simbolo #
. Campi e metodi privati non possono essere accessibili o modificati dall'esterno della classe.
Esempio:
- I campi privati
#name
e#age
sono dichiarati utilizzando il simbolo#
- I metodi
getName
,getAge
,setName
esetAge
permettono di interagire con i campi privati - Il tentativo di accesso ai campi privati dall'esterno della classe causa un errore
class Person {
#name; // campo privato
#age; // campo privato
constructor(name, age) {
this.#name = name;
this.#age = age;
}
getName() {
return this.#name;
}
getAge() {
return this.#age;
}
setName(name) {
this.#name = name;
}
setAge(age) {
if (age > 0) {
this.#age = age;
}
}
}
const person = new Person('Alice', 30);
console.log(person.getName()); // "Alice"
console.log(person.getAge()); // 30
person.setName('Bob');
person.setAge(25);
console.log(person.getName()); // "Bob"
console.log(person.getAge()); // 25
console.log(person.#name); // Errore: campo privato non accessibile
9.4 Metodi privati
Anche i metodi privati possono essere dichiarati utilizzando il simbolo #
e non sono accessibili dall'esterno della classe.
Esempio:
- Il campo privato
#balance
e il metodo privato#logTransaction
sono utilizzati per gestire lo stato dell'oggettoBankAccount
- Il metodo privato
#logTransaction
viene richiamato all'interno dei metodi pubblicideposit
ewithdraw
per registrare le transazioni
class BankAccount {
#balance;
constructor(initialBalance) {
this.#balance = initialBalance;
}
deposit(amount) {
if (amount > 0) {
this.#balance += amount;
this.#logTransaction('deposit', amount);
}
}
withdraw(amount) {
if (amount > 0 && amount <= this.#balance) {
this.#balance -= amount;
this.#logTransaction('withdraw', amount);
}
}
getBalance() {
return this.#balance;
}
#logTransaction(type, amount) {
console.log(`Transazione: ${type} ${amount}`);
}
}
const account = new BankAccount(1000);
account.deposit(500); // "Transazione: deposit 500"
console.log(account.getBalance()); // 1500
account.withdraw(200); // "Transazione: withdraw 200"
console.log(account.getBalance()); // 1300
account.#logTransaction('test', 100); // Errore: metodo privato non accessibile
GO TO FULL VERSION