Apex Academy
Módulo 5·06·22 min

Access Modifiers

private, public, protected y global deciden quién ve cada pieza de una clase. Encapsular es exponer acciones seguras en lugar de campos que cualquiera puede romper.

En Admin esField-Level Security: oculto, solo lectura o editable

✓ En esta sub-lección

  1. 01Elegir el modificador de acceso adecuado para cada atributo y método.
  2. 02Usar propiedades con { get; private set; } para exponer un valor en solo lectura.
  3. 03Proteger el estado de un objeto con métodos que validan, como una regla de validación.

La nutria: ¿Te acuerdas? · Repaso de la lección 5

¿Cómo llamas a un método static withVat de la clase PricingUtils?

Hasta ahora todo era public: cualquiera podía escribir ticket.hoursSpent = -40; y nadie lo impedía. En un equipo real, tu clase la usarán otras personas y otros procesos. Los modificadores de acceso deciden qué pueden tocar desde fuera, y eso es lo que mantiene los datos coherentes.

La nutria: El paralelo de Admin

Yo lo relaciono con dos cosas que configuras a diario: con Field-Level Security decides, campo a campo, si un perfil no lo ve, lo ve en solo lectura o lo puede editar. Y aunque un campo sea editable, una regla de validación impide guardar valores absurdos. Los modificadores de acceso hacen lo primero; los métodos que validan antes de cambiar un atributo hacen lo segundo.

Los cuatro niveles

ModificadorQuién lo veEn Salesforce sería…
privateSolo la propia claseUn campo oculto para todos los perfiles
protectedLa clase y las que heredan de ellaVisible solo para una «familia» de perfiles
publicTodo el código de tu orgVisible para todos los usuarios internos
globalTambién código de fuera: paquetes, integracionesPublicado en una API para terceros

Si no escribes nada delante de un atributo o método, Apex lo trata como private. La clase en sí, si es de primer nivel, tiene que ser public o global para que alguien la pueda usar. protected tendrá sentido en la próxima lección, con la herencia; global solo lo necesitarás si publicas un paquete o una API.

¿QUIÉN PREGUNTA?

  • private Boolean canAfford(…)private✗ invisible
  • protected Decimal reserveprotected✗ invisible
  • public Decimal spent { get; }leer: public✓ lo ve
  • spent { private set; }escribir: private✗ invisible
  • public Boolean spend(…)public✓ lo ve
  • global Decimal remaining()global✓ lo ve

Cualquier otra clase solo ve lo public: puede LEER spent, pero para cambiarlo tiene que pasar por spend(), que comprueba el presupuesto. Es el Field-Level Security de «solo lectura».

Cuanto más fuera está quien pregunta, menos piezas de la clase puede ver.

Propiedades: leer sí, escribir no

A menudo quieres que un valor se pueda leer desde fuera pero solo lo cambie la propia clase, como un campo de solo lectura en el page layout que sí actualiza la automatización. Apex tiene una forma corta para eso: la propiedad. public Decimal balance { get; private set; } se lee desde cualquier sitio, pero solo se asigna dentro de la clase.

Apex
public class CreditLine {
    public Decimal creditLimit { get; private set; }
    public Decimal usedAmount { get; private set; }

    public CreditLine(Decimal creditLimit) {
        this.creditLimit = creditLimit;
        this.usedAmount = 0;
    }

    // La única puerta para cambiar usedAmount: valida antes de tocar
    public Boolean charge(Decimal amount) {
        if (!fits(amount)) {
            return false;
        }
        usedAmount += amount;
        return true;
    }

    // Detalle interno: nadie de fuera necesita llamarlo
    private Boolean fits(Decimal amount) {
        return amount != null && amount > 0 && usedAmount + amount <= creditLimit;
    }
}

CreditLine line = new CreditLine(5000);
line.charge(3000);                 // true
System.debug(line.usedAmount);     // 3000: leer sí
line.usedAmount = 0;               // ❌ no compila: escribir no
Nadie puede dejar usedAmount por encima del límite, porque la única forma de cambiarlo pasa por la validación.

Encapsular: la regla vive dentro, no fuera

La razón de fondo para hacer private un atributo no es esconder datos por gusto: es que la regla que lo protege esté en un solo sitio. Si spent fuera public, cada trozo de código que gasta tendría que acordarse de comprobar el presupuesto antes; basta que uno lo olvide para que el presupuesto se supere. Con spent de solo lectura y un único método spend() que comprueba, es imposible saltarse la regla, venga la llamada de donde venga. Eso se llama encapsular.

La nutria: Una regla de validación dentro del objeto

Piensa en por qué confías en tus reglas de validación: se aplican igual si el registro se guarda desde la pantalla, desde una importación o desde la API, y nadie se las puede saltar. Un atributo privado con un método que comprueba es lo mismo en código: la regla viaja con el objeto. La diferencia es que en Apex la regla puede ser tan compleja como quieras, y el método puede devolver true o false en vez de mostrar un error.

La nutria: global y los paquetes que instalas

Esto lo vi instalando paquetes de AppExchange: desde tu org solo puedes usar las clases y métodos que el fabricante marcó como global; todo lo demás es invisible, aunque exista. Por eso en tu propio código casi nunca escribirás global: es la puerta que se deja abierta hacia fuera del paquete, y una vez publicada ya no se puede cerrar.