9.1 Conceitos Básicos
Encapsulamento é um dos conceitos-chave na programação orientada a objetos (POO) que permite esconder os detalhes internos da implementação de um objeto e fornecer acesso a esses detalhes por meio de interfaces bem definidas. Isso ajuda a melhorar a segurança e simplifica a gestão do código.
Vantagens do encapsulamento:
- Ocultação de dados: o encapsulamento permite esconder os detalhes internos da implementação e fornecer acesso apenas aos métodos e propriedades necessários. Isso evita o uso incorreto de objetos e melhora a segurança do código.
- Controle de acesso: o encapsulamento permite controlar o acesso aos dados e métodos, permitindo que o estado interno do objeto seja alterado apenas por meio de métodos específicos.
- Manutenibilidade: o encapsulamento melhora a manutenção do código, já que mudanças na implementação não afetam a interface externa da classe. Isso permite fazer alterações na implementação sem alterar o código que usa a classe.
- Melhoria nos testes: o encapsulamento permite isolar a implementação interna do objeto, o que facilita o teste unitário e reduz a probabilidade de efeitos colaterais.
No JavaScript, o encapsulamento é realizado usando métodos e propriedades, e a partir do ES2022, também se tornaram disponíveis campos e métodos privados.
9.2 Encapsulamento por meio de closures
Antes da introdução de campos privados no ES2022, o encapsulamento no JavaScript era frequentemente alcançado usando closures.
Exemplo:
- A variável
count
está disponível apenas dentro da funçãocreateCounter
e não está acessível externamente - Os métodos
increment
,decrement
egetCount
podem interagir com a variável privadacount
function createCounter() {
let count = 0; // variável privada
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 Campos Privados no ES2022
No ES2022, foram introduzidos campos e métodos privados, que são declarados usando o símbolo #
. Campos e métodos privados não podem ser acessados ou modificados externamente à classe.
Exemplo:
- Os campos privados
#name
e#age
são declarados usando o símbolo#
- Os métodos
getName
,getAge
,setName
esetAge
permitem interagir com os campos privados - Tentar acessar os campos privados externamente à classe resulta em erro
class Person {
#name; // campo privado
#age; // campo privado
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); // Erro: campo privado não acessível
9.4 Métodos Privados
Métodos privados também podem ser declarados usando o símbolo #
e não podem ser acessados externamente à classe.
Exemplo:
- O campo privado
#balance
e o método privado#logTransaction
são usados para gerenciar o estado do objetoBankAccount
- O método privado
#logTransaction
é chamado dentro dos métodos públicosdeposit
ewithdraw
para registrar transações
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(`Transaction: ${type} ${amount}`);
}
}
const account = new BankAccount(1000);
account.deposit(500); // "Transaction: deposit 500"
console.log(account.getBalance()); // 1500
account.withdraw(200); // "Transaction: withdraw 200"
console.log(account.getBalance()); // 1300
account.#logTransaction('test', 100); // Erro: método privado não acessível
GO TO FULL VERSION