9.1 Conceptos Básicos
Encapsulación es uno de los conceptos clave de la programación orientada a objetos (OOP), que permite ocultar los detalles internos de la implementación de un objeto y proporcionar acceso a estos detalles a través de interfaces estrictamente definidas. Esto ayuda a mejorar la seguridad y simplifica la gestión del código.
Ventajas de la encapsulación:
- Ocultación de datos: la encapsulación permite ocultar los detalles internos de la implementación y proporcionar acceso solo a los métodos y propiedades necesarios. Esto previene el uso incorrecto de los objetos y mejora la seguridad del código.
- Control de acceso: la encapsulación permite controlar el acceso a los datos y métodos, brindando la posibilidad de modificar el estado interno del objeto solo a través de métodos específicos.
- Mantenibilidad: la encapsulación mejora la mantenibilidad del código, ya que los cambios en la implementación no afectan la interfaz externa de la clase. Esto permite realizar modificaciones en la implementación sin cambiar el código que utiliza la clase.
- Mejora en las pruebas: la encapsulación permite aislar la implementación interna del objeto, lo cual facilita las pruebas unitarias y reduce la probabilidad de efectos secundarios.
En JavaScript, la encapsulación se implementa utilizando métodos y propiedades, y a partir de ES2022, también se han habilitado los campos y métodos privados.
9.2 Encapsulación a través de closures
Antes de la introducción de los campos privados en ES2022, la encapsulación en JavaScript a menudo se lograba usando closures.
Ejemplo:
- La variable
count
solo es accesible dentro de la funcióncreateCounter
y no es accesible desde fuera - Los métodos
increment
,decrement
ygetCount
pueden interactuar con la variable privadacount
function createCounter() {
let count = 0; // variable 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 en ES2022
En ES2022 se introdujeron los campos y métodos privados, que se declaran utilizando el símbolo #
. Los campos
y métodos privados no pueden ser accedidos ni modificados desde fuera de la clase.
Ejemplo:
- Los campos privados
#name
y#age
son declarados usando el símbolo#
- Los métodos
getName
,getAge
,setName
ysetAge
permiten interactuar con los campos privados - Cualquier intento de acceder a los campos privados desde fuera de la clase resulta en un error
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); // Error: campo privado no accesible
9.4 Métodos privados
Los métodos privados también pueden ser declarados usando el símbolo #
y no ser accesibles fuera de la clase.
Ejemplo:
- El campo privado
#balance
y el método privado#logTransaction
se utilizan para gestionar el estado del objetoBankAccount
- El método privado
#logTransaction
se invoca dentro de los métodos públicosdeposit
ywithdraw
para registrar las transacciones
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); // Error: método privado no accesible
GO TO FULL VERSION