Apex Academy
Módulo 5·02·20 min

Referencias: dos variables, un solo objeto

Una variable de tipo objeto no guarda el objeto: guarda el enlace a él. Copiar la variable copia el enlace, no el registro.

En Admin esDos pestañas abiertas del mismo registro

✓ En esta sub-lección

  1. 01Predecir qué pasa al asignar una variable de objeto a otra y modificar una de las dos.
  2. 02Hacer una copia independiente con clone() cuando la necesitas.
  3. 03Aprovechar las referencias para modificar registros desde un bucle o un método.

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

Si la clase es la definición del objeto, ¿qué es new WorkTicket()?

Con los números y los textos, copiar una variable copia el valor: cambiar la copia no toca el original. Con los objetos no ocurre así, y esa diferencia explica tanto uno de los errores más desconcertantes de Apex como uno de sus trucos más útiles.

La nutria: El paralelo de Admin

Te habrá pasado como a mí: abres la misma oportunidad en dos pestañas, cambias la etapa en una, guardas, refrescas la otra… y también ha cambiado. No hay dos oportunidades, hay dos ventanas al mismo registro. Una variable de objeto es una de esas pestañas: una al objeto, no el objeto.

Valores frente a referencias

Apex
// Valores: cada variable tiene su propia copia
Integer a = 5;
Integer b = a;
b = 10;
System.debug(a);            // 5

// Referencias: las dos variables apuntan al mismo objeto
Opportunity opp1 = new Opportunity(Name = 'Acme', StageName = 'Prospecting');
Opportunity opp2 = opp1;
opp2.StageName = 'Closed Won';
System.debug(opp1.StageName);   // Closed Won
opp2 = opp1 no fabrica otra oportunidad: copia el enlace. Solo hay un new, así que solo hay un objeto.
opp1 →opp2 →

UN solo objeto · lo miran opp1 y opp2

  • Name'Acme'
  • StageName'Prospecting'

Cuenta los new: ese es el número de objetos. Ahora cambia la etapa a través de opp2.

Cuenta los new: ese es el número de objetos. Las variables son solo flechas hacia ellos.

Integer, Decimal, Boolean, Date y String se comportan como valores: puedes copiarlos sin miedo. Los sObjects, las colecciones y las instancias de tus clases se comportan como referencias. Regla práctica: si se creó con new, piensa en enlaces.

El lado útil: cambiar registros desde un bucle

Por esto funciona algo que hiciste en el Módulo 2 sin pensarlo: en for (Lead l : leads), l no es una copia, es una referencia al registro de la lista. Si cambias l.Rating, cambia el lead que está dentro de leads. Lo mismo ocurre cuando pasas un objeto a un método: el método recibe el enlace y puede modificar el objeto original. Así trabajarán tus triggers en el Módulo 6.

Apex
for (Lead l : leads) {
    l.Rating = 'Hot';        // cambia el lead que está en la lista
}
System.debug(leads[0].Rating);   // Hot

Cuando necesitas una copia de verdad: clone()

Si lo que quieres es un segundo registro independiente (una renovación que parte de la oportunidad de este año), pide una copia: original.clone() fabrica un objeto nuevo con los mismos valores. A partir de ahí, cambiar uno no toca el otro. Las listas también tienen clone().

Apex
Opportunity renewal = original.clone();   // otro objeto, mismos valores
renewal.StageName = 'Prospecting';
System.debug(original.StageName);           // sigue igual

Un objeto en dos colecciones a la vez

Las referencias no solo aparecen al copiar variables: aparecen cada vez que guardas el mismo objeto en dos colecciones. Es muy habitual en triggers: tienes la lista de cuentas y construyes un Map por Id para buscarlas rápido. Lista y Map no tienen copias distintas, tienen flechas hacia las MISMAS cuentas. Cambia una a través del Map y el cambio se ve también desde la lista.

Apex
List<Account> accounts = [SELECT Id, Name, Rating FROM Account LIMIT 10];
Map<Id, Account> byId = new Map<Id, Account>(accounts);

Account acme = byId.get(accounts[0].Id);
acme.Rating = 'Hot';

System.debug(accounts[0].Rating); // Hot: es el mismo objeto
Por eso, en el Módulo 7, el servicio podía cambiar la prioridad de los casos que recibía y el cambio llegaba a Trigger.new.

La nutria: El mismo contacto en dos related lists

Otro ejemplo que me ayudó: un contacto aparece en la related list de su cuenta y también en la de una campaña de la que es miembro. Si le cambias el teléfono desde la campaña, en la cuenta también sale cambiado: no hay dos contactos, hay uno visto desde dos sitios. Eso es exactamente una referencia. Lo que en Apex sería una copia de verdad (clone()) en la interfaz sería el botón «Clonar»: un registro nuevo que a partir de ahí va por su cuenta.