Apex Academy
Módulo 5·07·22 min

Herencia

Una clase hija recibe todo lo de su clase padre y añade lo suyo. En Apex, además, el padre tiene que dar permiso para ser heredado.

En Admin esLos campos estándar que todo objeto trae de serie, más los personalizados que añades tú

✓ En esta sub-lección

  1. 01Crear una clase hija con extends a partir de una clase padre marcada virtual.
  2. 02Llamar al constructor del padre con super(…) y usar protected para compartir con las hijas.
  3. 03Reconocer cuándo la relación «es un» justifica heredar.

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

Una propiedad public Decimal spent { get; private set; }, ¿quién puede cambiarla?

Imagina que tienes una clase Notification con destinatario, asunto y un método para previsualizarla. Ahora necesitas recordatorios de tareas: son notificaciones, pero con fecha de vencimiento. Copiar la clase entera y añadir un campo funcionaría… hasta que alguien arregle un fallo en una copia y no en la otra. La herencia evita esa copia.

La nutria: El paralelo de Admin

Cuando creé mi primer objeto personalizado me sorprendió que ya trajera Id, Name, OwnerId, CreatedDate y LastModifiedDate. No los defines: los hereda de lo que todo objeto de Salesforce tiene en común. Tú solo añades los campos que lo hacen distinto. Una clase hija es eso: todo lo del padre, más lo suyo.

Padre e hija

Apex
public virtual class Notification {
    protected String recipient;
    public String subject;

    public Notification(String recipient, String subject) {
        this.recipient = recipient;
        this.subject = subject;
    }

    public String preview() {
        return subject + ' → ' + recipient;
    }
}

public class TaskReminder extends Notification {
    public Date dueDate;

    public TaskReminder(String recipient, String subject, Date dueDate) {
        super(recipient, subject);     // el padre rellena lo suyo
        this.dueDate = dueDate;        // la hija, lo suyo
    }

    public Boolean isOverdue() {
        return dueDate < Date.today();
    }
}
  • extends Notification: TaskReminder hereda recipient, subject y preview() sin volver a escribirlos.
  • virtual en el padre: en Apex, una clase no se puede heredar a menos que lo permita. Sin virtual, extends Notification no compila.
  • super(…) llama al constructor del padre y tiene que ir en la primera línea, igual que this(…).
  • protected: recipient es invisible para el resto de la org, pero TaskReminder sí puede usarlo. Es el nivel de acceso «solo para la familia».
  • recipient (protected)heredado de Notification
  • subjectheredado de Notification
  • preview()heredado de Notification
  • dueDatepropio de TaskReminder
  • isOverdue()propio de TaskReminder
reminder.preview() → 'Llamar a Acme → ana@acme.com'

TaskReminder tiene todo lo de Notification —sin volver a escribirlo— y además lo suyo. Como un perfil base con un permission set encima (simplificación: en Apex solo se hereda de una clase).

La hija no copia al padre: lo amplía. Un arreglo en preview() llega a todas las hijas a la vez.

Usar la hija

Apex
TaskReminder reminder = new TaskReminder('ana@acme.com', 'Llamar a Acme', Date.today().addDays(-1));
System.debug(reminder.preview());     // heredado: Llamar a Acme → ana@acme.com
System.debug(reminder.isOverdue());   // propio: true

Notification anyNotice = reminder;    // una TaskReminder ES una Notification
La última línea anticipa el polimorfismo: donde se espera un padre, vale cualquier hija.

Lo que se hereda y lo que no

La hija recibe los atributos y métodos públicos y protected del padre. Lo private del padre sigue existiendo dentro del objeto, pero la hija no puede tocarlo: por eso recipient es protected, para que TaskReminder pueda usarlo. Y hay algo que NO se hereda nunca: los constructores. Si el padre solo tiene un constructor con parámetros, la hija tiene que escribir el suyo y llamar al del padre con super(…) como primera línea. Es la forma de decir «primero construye la parte de notificación, y luego yo añado lo mío».

Apex
public class TaskReminder extends Notification {
    private Date dueDate;

    public TaskReminder(String recipient, String subject, Date dueDate) {
        super(recipient, subject);   // 1º: el padre monta su parte
        this.dueDate = dueDate;      // 2º: la hija añade la suya
    }
}

La nutria: Un perfil base y lo que se añade encima

Simplificación útil, la que yo usé: piensa en un perfil mínimo que todos comparten y en los permission sets que se suman encima para cada rol. El comercial tiene todo lo del perfil base y además lo suyo; si mañana arreglas algo en el perfil, lo reciben todos a la vez. La herencia funciona así: lo común se escribe una vez en el padre y cada hija añade lo que la hace distinta. (Donde la analogía falla: un usuario puede sumar varios permission sets, y en Apex una clase solo puede heredar de UNA.)