Extender enumeraciones en Java

Sheeraz Gul 12 octubre 2023
Extender enumeraciones en Java

Este tutorial demuestra cómo extender la funcionalidad enumeración en Java.

Extender enumeración en Java

Podemos considerar enum como una especie de magia del compilador porque, en el código byte, el enum se representa como una clase con varios miembros estáticos y se hereda del resumen java.lang.Enum.

Es la razón por la que enumeración no puede extenderse a ninguna otra clase o enumeración. Como no podemos extender enumeración en Java, tampoco es posible que ninguna clase extienda una enumeración. Aprendamos usando el siguiente código de ejemplo y veamos qué sucede.

Código de ejemplo:

package delftstack;

enum Cars { Audi, BMW, Marcedes }

public class Example extends Cars {
  public static void main(String... args) {}
}

El código anterior tiene una enumeración llamada Coches, y la clase Ejemplo está tratando de extenderla. Ver salida:

/Example.java:5: error: cannot inherit from final Cars
public class Example extends Cars {
                             ^
/Example.java:5: error: enum types are not extensible
public class Example extends Cars {
       ^
2 errors

Como podemos ver, la clase no puede extender el enum. Entonces, si es imposible extender la enumeración, ¿podemos aún extender su funcionalidad?

La funcionalidad se puede definir como los métodos implementados en el enum. Por ejemplo, el enum Cars del código anterior puede declarar métodos abstractos para cada miembro; ver el ejemplo:

enum Cars {
  Audi {
    @Override
    public void drive() {}
  },
  BMW {
    @Override
    public void drive() {}
  },
  Mercedes {
    @Override
    public void drive() {}
  },
  ;
  public abstract void drive();
}

Como podemos ver, cada miembro puede anular el método drive(). Pero desafortunadamente, no siempre es posible crear métodos en enum porque:

  • Si el enum pertenece a una biblioteca de terceros oa otro equipo, no permitirá la implementación de métodos abstractos.
  • Si pertenece al módulo que no tiene la dependencia requerida para el método drive().
  • Si el enumerado está sobrecargado con otras funciones y datos, será ilegible.

Se proporcionan algunas soluciones que pueden resolver estos problemas y ampliar la funcionalidad de enum en Java.

Solución 1: espejo enum en Java

Como sugiere el nombre, necesitamos crear otra enumeración con los mismos datos. Esa nueva enumeración también implementará el método drive(), por lo que ahora tenemos dos enumeraciones:

Código de ejemplo para enum Cars:

enum Cars {
  Audi {
    @Override
    public void drive() {}
  },
  BMW {
    @Override
    public void drive() {}
  },
  Mercedes {
    @Override
    public void drive() {}
  },
  ;
  public abstract void drive();
}

Código de ejemplo para enum DriveCars:

enum DriveCars {
  Audi {
    @Override
    public void drive() {}
  },
  BMW {
    @Override
    public void drive() {}
  },
  Mercedes {
    @Override
    public void drive() {}
  },
  ;
  public abstract void drive();
}

El segundo enumerado es el espejo del primero. Ahora podemos usar ambas enumeraciones extendiendo la funcionalidad; necesitamos usar métodos integrados enum que son name() y valueof().

Vea el siguiente ejemplo de cómo usarlo:

Cars cars = ... DriveCars.valueOf(cars.name()).drive();

El código anterior muestra cómo se usa la funcionalidad enum Cars en enum DriveCars. Lo que significa que la funcionalidad se amplía.

El método name() en el código anterior es final, que no se puede anular, y el compilador generará el método valueOf. Ambos métodos encajan bien entre sí si no hay ningún error funcional en la operación extendida.

Hay un problema con el código anterior si se cambia el enum Cars, el enum DriveCars no tendrá ninguna idea, y causará la falla del truco name y valueof. Para resolver este problema, debemos informar a DriveCars que su espejo principal es Cars.

Para eso, podemos usar un inicializador estático para comparar DriveCars y Cars, que arrojará la excepción si ambas enumeraciones no coinciden. Aquí hay un ejemplo de eso de la biblioteca enumus:

enum DriveCars {
  ....static { Mirror.of(Cars.class); }
}

La clase de utilidad verificará si ambas enumeraciones coinciden o no. Este método validará el truco name() y valueOf().

Solución 2: Mapa enum en Java

Si no desea crear otra enumeración que contenga solo un método. En este caso, podemos usar interfaz en lugar de enum; vea el ejemplo a continuación:

public interface Driver {
  void drive();
}

Ahora, para usar esta interfaz Drive con la enumeración Cars, podemos crear un mapeo entre ellos. Aquí está el ejemplo para el mapa:

Map<Cars, Driver> drivers = new EnumMap<>(Cars.class) {
  {
    put(Audi, new Driver() {
      @Override
      public void driver() {}
    }) put(BMW, new Driver() {
      @Override
      public void driver() {}
    }) put(Mercedes, new Driver() {
      @Override
      public void driver() {}
    })
  }
}

Ahora, para usarlos, use este simple código:

drivers.get(Cars).drive();

El EnumMap utilizado en el código anterior garantizará que cada miembro enum aparecerá solo una vez, pero no garantiza una entrada para cada miembro.

Podemos comprobar que el tamaño del mapa es igual al número de miembros de las enumeraciones:

drivers.size() == Cars.values().length

La biblioteca enumus también proporciona una utilidad para este caso: si el mapa no se ajusta a los Cars, lanzará la IllegalStateException. Aquí está la utilidad:

EnumMapValidator.validateValues(Cars.class, map, "Cars map");

Ambos métodos anteriores muestran cómo hacer que las enumeraciones sean poderosas al extender su funcionalidad. Aunque es imposible extender directamente una enumeración, podemos usar estos trucos para ampliar sus funcionalidades.

Sheeraz Gul avatar Sheeraz Gul avatar

Sheeraz is a Doctorate fellow in Computer Science at Northwestern Polytechnical University, Xian, China. He has 7 years of Software Development experience in AI, Web, Database, and Desktop technologies. He writes tutorials in Java, PHP, Python, GoLang, R, etc., to help beginners learn the field of Computer Science.

LinkedIn Facebook

Artículo relacionado - Java Enum