Modificadores de acceso: public, private y protected
Los modificadores de acceso controlan desde dónde se pueden leer o modificar las propiedades y métodos de una clase, protegiendo la integridad del estado interno.
public: accesible desde cualquier lugar
public es el modificador por defecto. Las propiedades y métodos públicos se pueden acceder desde cualquier lugar: dentro de la clase, en subclases y desde fuera:
class Producto {
public nombre: string; // public es el default
public precio: number;
constructor(nombre: string, precio: number) {
this.nombre = nombre;
this.precio = precio;
}
public describir(): string {
return `${this.nombre} cuesta $${this.precio}`;
}
}
const p = new Producto("Laptop", 1200);
// Acceso desde fuera ✅
console.log(p.nombre); // "Laptop"
console.log(p.precio); // 1200
console.log(p.describir()); // "Laptop cuesta $1200"
// Modificación desde fuera ✅
p.precio = 999;
console.log(p.precio); // 999Laptop
1200
Laptop cuesta $1200
999No necesitas escribir public explícitamente — es el comportamiento por defecto. Sin embargo, escribirlo mejora la legibilidad y hace explícita la intención del diseño.
private: solo dentro de la clase
private restringe el acceso a dentro de la clase únicamente. Ni las subclases ni el código externo pueden leer o modificar la propiedad:
class CuentaBancaria {
public titular: string;
private saldo: number;
constructor(titular: string, saldoInicial: number) {
this.titular = titular;
this.saldo = saldoInicial;
}
depositar(monto: number): void {
if (monto <= 0) throw new Error("El monto debe ser positivo");
this.saldo += monto;
}
retirar(monto: number): void {
if (monto > this.saldo) throw new Error("Saldo insuficiente");
this.saldo -= monto;
}
obtenerSaldo(): number {
return this.saldo; // ← método público que expone saldo de forma controlada
}
}
const cuenta = new CuentaBancaria("Ana", 1000);
cuenta.depositar(500);
console.log(cuenta.obtenerSaldo()); // 1500
// ❌ Error: Property 'saldo' is private
// console.log(cuenta.saldo);
// cuenta.saldo = 999999;1500TypeScript tiene su propio private (solo en tiempo de compilación) y también soporta el # privado de JavaScript (privacidad en runtime). Usa private para la mayoría de los casos; usa #campo cuando necesites privacidad real en runtime.
protected: clase y subclases
protected permite el acceso dentro de la clase y en todas sus subclases, pero no desde el exterior:
class Empleado {
public nombre: string;
protected salarioBase: number; // accesible en subclases
constructor(nombre: string, salario: number) {
this.nombre = nombre;
this.salarioBase = salario;
}
protected calcularImpuesto(): number {
return this.salarioBase * 0.15; // método protegido
}
getSalarioNeto(): number {
return this.salarioBase - this.calcularImpuesto();
}
}
class Gerente extends Empleado {
private bono: number;
constructor(nombre: string, salario: number, bono: number) {
super(nombre, salario);
this.bono = bono;
}
// Puede acceder a salarioBase y calcularImpuesto porque son protected
override getSalarioNeto(): number {
const impuesto = this.calcularImpuesto(); // ✅ protected
return this.salarioBase + this.bono - impuesto; // ✅ protected
}
}
const emp = new Empleado("Carlos", 3000);
const ger = new Gerente("Diana", 5000, 1500);
console.log(emp.getSalarioNeto()); // 2550
console.log(ger.getSalarioNeto()); // 5750
// ❌ Error desde fuera: salarioBase es protected
// console.log(emp.salarioBase);2550
5750readonly: solo asignable en el constructor
readonly permite leer la propiedad desde cualquier lugar, pero solo asignarla durante la inicialización:
class Configuracion {
readonly nombre: string;
readonly version: string;
readonly creadoEn: Date;
constructor(nombre: string, version: string) {
this.nombre = nombre;
this.version = version;
this.creadoEn = new Date();
}
describir(): string {
return `${this.nombre} v${this.version}`;
}
}
const config = new Configuracion("MiApp", "1.0.0");
console.log(config.nombre); // "MiApp"
console.log(config.describir()); // "MiApp v1.0.0"
// ❌ Error: Cannot assign to 'nombre' because it is a read-only property
// config.nombre = "OtraApp";
// readonly + private: encapsulación total
class Usuario {
private readonly id: number;
public nombre: string;
constructor(id: number, nombre: string) {
this.id = id;
this.nombre = nombre;
}
getId(): number {
return this.id; // se puede leer, no modificar
}
}
const u = new Usuario(42, "Ana");
console.log(u.getId()); // 42MiApp
MiApp v1.0.0
42| Modificador | Dentro de la clase | Subclases | Desde fuera |
|---|---|---|---|
| public | Sí | Sí | Sí |
| protected | Sí | Sí | No |
| private | Sí | No | No |
| readonly | Solo en constructor | Lectura sí | Solo lectura |