0Pricing
Java Academy · Lección

Métodos abstractos en enums

Comportamiento por constante

Métodos abstractos en enums es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.

Comportamiento por constante

A veces cada constante de una enumeración necesita un comportamiento diferente, no solo datos diferentes.

Java permite declarar un método abstracto en la enumeración y sobrescribirlo para cada constante. Este es el patrón de cuerpo de método específico de cada constante.

public class Main {
    enum Operation {
        PLUS { public int apply(int a, int b) { return a + b; } },
        MINUS { public int apply(int a, int b) { return a - b; } };
        public abstract int apply(int a, int b);
    }
    public static void main(String[] args) {
        System.out.println(Operation.PLUS.apply(3, 4));
        System.out.println(Operation.MINUS.apply(10, 6));
    }
}

Cómo funciona

Cada constante que tiene un cuerpo se convierte en una subclase anónima de la enumeración.

El método abstracto obliga a cada constante a proporcionar una implementación, por lo que el compilador garantiza que no falte ninguna.

public class Main {
    enum Operation {
        TIMES { public int apply(int a, int b) { return a * b; } };
        public abstract int apply(int a, int b);
    }
    public static void main(String[] args) {
        // The constant is an instance of a generated subclass
        System.out.println(Operation.TIMES.getClass().getSimpleName().isEmpty()
            ? "anonymous subclass" : Operation.TIMES.apply(6, 7));
    }
}

Una calculadora completa

Las cuatro operaciones aritméticas se representan como constantes, cada una con su propio cuerpo de apply.

public class Main {
    enum Operation {
        PLUS  { public double apply(double a, double b) { return a + b; } },
        MINUS { public double apply(double a, double b) { return a - b; } },
        TIMES { public double apply(double a, double b) { return a * b; } },
        DIVIDE{ public double apply(double a, double b) { return a / b; } };
        public abstract double apply(double a, double b);
    }
    public static void main(String[] args) {
        double x = 6, y = 3;
        for (Operation op : Operation.values()) {
            System.out.printf("%s -> %.1f%n", op, op.apply(x, y));
        }
    }
}

Combinar campos y comportamiento

Puede combinar un campo (un símbolo) con comportamiento específico para cada constante. El campo identifica la operación y el método la ejecuta.

public class Main {
    enum Operation {
        PLUS("+")  { public double apply(double a, double b) { return a + b; } },
        MINUS("-") { public double apply(double a, double b) { return a - b; } };
        private final String symbol;
        Operation(String symbol) { this.symbol = symbol; }
        public abstract double apply(double a, double b);
        @Override public String toString() { return symbol; }
    }
    public static void main(String[] args) {
        Operation op = Operation.PLUS;
        System.out.println("2 " + op + " 3 = " + op.apply(2, 3));
    }
}

¿Por qué no usar un switch?

Podría implementar apply con un único switch sobre la constante, pero el enfoque del método abstracto es más seguro.

Si añade una constante más adelante, el compilador le obliga a proporcionar su cuerpo. Un switch podría omitir silenciosamente el caso nuevo.

public class Main {
    enum Op {
        SQUARE { public int apply(int n) { return n * n; } },
        CUBE   { public int apply(int n) { return n * n * n; } };
        public abstract int apply(int n);
    }
    public static void main(String[] args) {
        System.out.println(Op.SQUARE.apply(5));
        System.out.println(Op.CUBE.apply(3));
    }
}

Métodos concretos junto a métodos abstractos

Una enumeración puede combinar métodos abstractos y concretos. La lógica compartida se coloca en un método concreto; la lógica variable permanece abstracta.

public class Main {
    enum Shape {
        CIRCLE { public double area(double x) { return Math.PI * x * x; } },
        SQUARE { public double area(double x) { return x * x; } };
        public abstract double area(double x);
        public String report(double x) { return this + " area = " + area(x); }
    }
    public static void main(String[] args) {
        System.out.println(Shape.CIRCLE.report(2));
    }
}

Enumeraciones de estrategia

Una variante es la enumeración de estrategia: las constantes delegan en una enumeración de estrategia anidada en lugar de sobrescribir directamente el método.

Esto resulta útil cuando varias constantes comparten el mismo comportamiento. En este caso, los días laborables y los fines de semana difieren en el cálculo del pago.

public class Main {
    enum PayType {
        WEEKDAY { int overtime(int mins) { return mins; } },
        WEEKEND { int overtime(int mins) { return mins * 2; } };
        abstract int overtime(int mins);
        int pay(int mins) { return mins + overtime(Math.max(0, mins - 480)); }
    }
    public static void main(String[] args) {
        System.out.println("Weekend pay: " + PayType.WEEKEND.pay(540));
    }
}

Enumeración con interfaz y cuerpos

Combine una interfaz con cuerpos específicos para cada constante para lograr el máximo polimorfismo.

public class Main {
    interface Command { String run(); }
    enum Action implements Command {
        START { public String run() { return "starting..."; } },
        STOP  { public String run() { return "stopping..."; } };
    }
    public static void main(String[] args) {
        for (Action a : Action.values()) System.out.println(a.run());
    }
}

Acceder a campos desde los cuerpos

Un cuerpo específico de una constante puede leer los campos propios de esa constante, ya que cada cuerpo se ejecuta en el contexto de esa instancia.

public class Main {
    enum Tax {
        STANDARD(0.20) { double apply(double amt) { return amt * (1 + rate); } },
        REDUCED(0.05)  { double apply(double amt) { return amt * (1 + rate); } };
        protected final double rate;
        Tax(double rate) { this.rate = rate; }
        abstract double apply(double amt);
    }
    public static void main(String[] args) {
        System.out.printf("%.2f%n", Tax.STANDARD.apply(100));
    }
}

Valor predeterminado y sobrescritura

Puede proporcionar un valor predeterminado concreto en el cuerpo de la enumeración y sobrescribirlo únicamente para las constantes que se comporten de forma diferente.

public class Main {
    enum Notifier {
        EMAIL,
        SMS { String send(String m) { return "SMS: " + m; } };
        String send(String m) { return "EMAIL: " + m; }
    }
    public static void main(String[] args) {
        System.out.println(Notifier.EMAIL.send("hi"));
        System.out.println(Notifier.SMS.send("hi"));
    }
}

Una máquina de estados pequeña

El comportamiento por constante resulta especialmente útil en las máquinas de estados: cada estado conoce su propia transición.

public class Main {
    enum State {
        IDLE    { State next() { return RUNNING; } },
        RUNNING { State next() { return DONE; } },
        DONE    { State next() { return DONE; } };
        abstract State next();
    }
    public static void main(String[] args) {
        State s = State.IDLE;
        for (int i = 0; i < 3; i++) { System.out.println(s); s = s.next(); }
        System.out.println(s);
    }
}

Comprobación rápida

Compruebe cuánto entiende sobre los métodos abstractos de las enumeraciones.

Repaso

Ha aprendido sobre el comportamiento por constante:

  • Declare un método abstracto y sobrescríbalo en el cuerpo de cada constante.
  • Cada constante se convierte en una subclase anónima.
  • El compilador exige que no falte ninguna implementación, lo que resulta más seguro que un switch.
  • Combine campos, valores predeterminados concretos e interfaces para crear enumeraciones completas.

A continuación, EnumSet, la colección de alto rendimiento.

public class Main {
    enum E { A { int v() { return 1; } }; abstract int v(); }
    public static void main(String[] args) {
        System.out.println("Abstract enum recap: " + E.A.v());
    }
}

Preguntas frecuentes

¿La lección «Métodos abstractos en enums» es gratis?

Sí — el texto completo de «Métodos abstractos en enums» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Métodos abstractos en enums»?

Comportamiento por constante Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Java Academy?

No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.

¿Cuánto tiempo toma la lección «Métodos abstractos en enums»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Java Academy?

Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Enums con campos y métodos
  2. Métodos abstractos en enums
  3. EnumSet
  4. EnumMap
← Volver a Java Academy