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 esta sub-lección
- 01Predecir qué pasa al asignar una variable de objeto a otra y modificar una de las dos.
- 02Hacer una copia independiente con clone() cuando la necesitas.
- 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
Valores frente a referencias
// 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 WonUN 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.
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.
for (Lead l : leads) {
l.Rating = 'Hot'; // cambia el lead que está en la lista
}
System.debug(leads[0].Rating); // HotCuando 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().
Opportunity renewal = original.clone(); // otro objeto, mismos valores
renewal.StageName = 'Prospecting';
System.debug(original.StageName); // sigue igualUn 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.
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 objetoLa nutria: El mismo contacto en dos related lists