Apex Academy
Módulo 5·11·22 min

Clases internas y Enums

Un enum es una lista cerrada de valores que el compilador vigila. Una clase interna agrupa datos que solo tienen sentido junto a su clase, como una fila de informe con columnas de varios objetos.

En Admin esUn picklist restringido (enum) y una fila de informe con columnas de varios objetos (clase wrapper)

✓ En esta sub-lección

  1. 01Declarar un enum, usar sus valores y recorrerlo con switch.
  2. 02Escribir una clase interna y usarla desde fuera con Externa.Interna.
  3. 03Reconocer el patrón wrapper: juntar en un objeto datos que vienen de sitios distintos.

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

Añades una tercera regla de scoring que implementa LeadScoringRule. ¿Cuántas líneas del bucle cambian?

Dos herramientas pequeñas para cerrar el módulo, y las dos las verás en casi cualquier org. Los enums acaban con los errores de escribir mal un texto. Las clases internas mantienen juntas las piezas que solo existen para servir a una clase.

La nutria: El paralelo de Admin

Yo lo veo así: un picklist restringido solo acepta sus valores; nadie puede guardar 'Hgih' en Priority. Un enum es eso, pero lo vigila el compilador: si escribes un valor que no existe, la clase ni siquiera se guarda. Y una clase wrapper es como una fila de un informe con columnas de Account y de Opportunity: un objeto hecho a medida para llevar juntos datos de varios sitios.

Enum: una lista cerrada de valores

Apex
public enum Tier { STANDARD, PRIORITY, CRITICAL }

Tier current = Tier.CRITICAL;
Tier typo = Tier.CRITCAL;        // ❌ no compila: ese valor no existe
String asText = 'CRITCAL';       // ✅ compila… y el error aparecerá en producción

System.debug(current.name());     // CRITICAL
System.debug(current.ordinal());  // 2: su posición, empezando en 0
System.debug(Tier.values());      // (STANDARD, PRIORITY, CRITICAL)
Con un String, una errata es un bug silencioso. Con un enum, es un error al guardar que solo ves tú.

Los enums encajan de maravilla con el switch del Módulo 2. Hay una particularidad: en los when se escribe solo el valor, sin el nombre del enum delante. Y como el compilador conoce todos los valores, un enum es mucho más seguro que repartir por textos.

Apex
switch on current {
    when CRITICAL { slaHours = 4; }      // CRITICAL, no Tier.CRITICAL
    when PRIORITY { slaHours = 24; }
    when else     { slaHours = 72; }
}

Clases internas y el patrón wrapper

Una clase puede declarar otra dentro de sus llaves. Desde fuera se nombra como Externa.Interna. Se usa sobre todo para el patrón wrapper: un objeto pequeño que junta datos de varios registros (el nombre del caso, su nivel, sus horas de respuesta) y que solo tiene sentido para esa clase. Lo verás muchísimo cuando envíes datos a una pantalla con LWC.

Apex
public class CaseRouter {
    public enum Tier { STANDARD, PRIORITY, CRITICAL }

    public class Assignment {                 // clase interna (wrapper)
        public String caseSubject;
        public Tier tier;
        public Integer slaHours;
    }

    public static Assignment route(Case c) {
        Assignment result = new Assignment();
        result.caseSubject = c.Subject;
        result.tier = c.Priority == 'High' ? Tier.CRITICAL : Tier.STANDARD;
        result.slaHours = result.tier == Tier.CRITICAL ? 4 : 72;
        return result;
    }
}

CaseRouter.Assignment a = CaseRouter.route(new Case(Subject = 'Portal caído', Priority = 'High'));
System.debug(a.tier.name() + ' · ' + a.slaHours);   // CRITICAL · 4
Dentro de CaseRouter basta con Assignment y Tier; desde fuera se escriben CaseRouter.Assignment y CaseRouter.Tier.

✓ Compila. slaHours = 4.

Un enum es una lista cerrada que vigila el compilador: una errata no llega nunca a ejecutarse. Un picklist restringido hace lo mismo con los datos; el enum, con el código.

La clase externa agrupa su enum y su wrapper: quien la usa lo encuentra todo bajo un mismo nombre.

El wrapper que verás en cualquier entrevista

El uso más famoso de una clase interna es el wrapper para pantallas: una tabla de cuentas con una casilla para seleccionar varias y actuar sobre ellas. Account no tiene ningún campo «seleccionado», y crear uno en el objeto solo para una pantalla sería ensuciar el modelo de datos. La solución es un wrapper que junta el registro y la casilla. Es tan habitual que en las entrevistas de desarrollador Salesforce se pregunta casi siempre.

Apex
public class AccountPicker {
    public class Row {
        public Boolean selected = false;   // lo que la cuenta no tiene
        public Account record;             // el registro, entero
        public Row(Account record) { this.record = record; }
    }
}

List<AccountPicker.Row> rows = new List<AccountPicker.Row>();
for (Account a : [SELECT Id, Name FROM Account LIMIT 20]) {
    rows.add(new AccountPicker.Row(a));
}

La nutria: Picklist restringido o enum: dónde vive la lista

Esta distinción me costó: un picklist restringido protege los DATOS; nadie puede guardar un valor que no esté en la lista, ni siquiera por API. Un enum protege el CÓDIGO: nadie puede escribir un valor que no exista, porque no compila. Y hay una diferencia práctica: un Admin cambia los valores del picklist desde Setup cuando quiere; los de un enum solo cambian con un despliegue. Por eso los enums se usan para listas que son parte de la lógica (niveles de servicio, estados internos), no para las que decide el negocio cada trimestre.