Can we extend enum class in java

Two ways to extend enum functionality

In my previous article I explained how and why to use enums instead of switch/case control structure in Java code. Here I will show how to extend functionality of existing enums .

Introduction

Java enum is a kind of a compiler magic. In the byte code any enum is represented as a class that extends abstract class java.lang.Enum and has several static members. Therefore enum cannot extend any other class or enum: there is no multiple inheritance. Class cannot extend enum as well. This limitation is enforced by compiler. Here is a simple enum :

Enum cannot either extend or be extended. So, how is it possible to extend its functionality? The key word is “functionality”. Enum can implement methods. For example enum Color may declare abstract method draw() and each member can override it:

enum Color < red < @Override public void draw() < >>, green < @Override public void draw() < >>, blue < @Override public void draw() < >>, ; public abstract void draw(); >

Popular usage of this technique is explained here. Unfortunately it is no always possible to implement method in enum itself because:

  1. the enum may belong to third party library or other team in the company
  2. the enum is probably overloaded with too many other data and functions so it becomes not readable
  3. the enum belongs to module that does not have dependencies required for implementation of method draw().

This article suggests the following solutions for this problem.

Mirror enum

We cannot modify enum Color? No problem! Let’s create enum DrawableColor that has exactly same elements as Color. This new enum will implement our method draw():

enum DrawableColor < red < @Override public void draw() < >>, green < @Override public void draw() < >>, blue < @Override public void draw() < >>, ; public abstract void draw(); >

This enum is a kind of reflection of source enum Color , i.e. Color is its mirror.But how to use the new enum? All our code uses Color , not DrawableColor . The simplest way to implement this transition is using built-in enum methods name() and valueOf() as following:

Color color = . DrawableColor.valueOf(color.name()).draw();

Since name() method is final and cannot be overridden and valueOf() is generated by a compiler these methods are always fit each other, so no functional problems are expected here. Performance of such transition is good also: method name() even does not create new String but returns pre-initialized one (see source code of java.lang.Enum ). Method valueOf() is implemented using Map, so its complexity is O(1).

The code above contains obvious problem. If source enum Color is changed the secondary enum DrawableColor does not know this fact, so the trick with name() and valueOf() will fail at runtime. We do not want this to happen. But how to prevent possible failure?

We have to let DrawableColor to know that its mirror is Color and enforce this preferably at compile time or at least at unit test phase. Here we suggest validation during unit tests execution. Enum can implement static initializer that is executed when enum is mentioned in any code. This actually means that if static initializer validates that enum DrawableColor fits Color it is enough to implement test like following to be sure that the code will be never broken in production environment:

Читайте также:  Java properties get keys

@Test public void drawableColorFitsMirror

Static initializer just have to compare elements of DrawableColor and Color and throw exception if they do not match. This code is simple and can be written for each particular case. Fortunately simple open source library named enumus already implements this functionality, so the task becomes trivial:

That’s it. The test will fail if source enum and DrawableColor do not fit it any more. Utility class Mirror has other method that gets 2 arguments: classes of 2 enums that have to fit. This version can be called from any place in code and not only from enum that has to be validated.

EnumMap

Do we really have to define another enum that just holds implementation of one method? In fact, we do not have to. Here is an alternative solution. Let’s define interface Drawer as following:

Now let’s create mapping between enum elements and implementation of interface Drawer:

Map drawers = new EnumMap<>(Color.class) ); put(green, new Drawer() < @Override public void draw();>) put(blue, new Drawer() < @Override public void draw();>) >>

EnumMap is chosen here as a Map implementation for better performance. Map guaranties that each enum element appears there only once. However, it does not guarantee that there is entry for each enum element. But it is enough to check that size of the map is equal to number of enum elements:

Enumus suggests convenient utility for this case also. The following code throws IllegalStateException with descriptive message if map does not fit Color:

It is important to call the validator from the code which is executed by unit test. In this case the map based solution is safe for future modifications of source enum.

EnumMap and Java 8 functional interface

In fact, we do not have to define special interface to extend
enum functionality. We can use one of functional interfaces provided by JDK starting from version 8 ( Function,BiFunction,Consumer,BiConsumer,
Supplieretc .) The choice depends on parameters that have to be sent to the function. For example, Supplier can be used instead of Drawable defined in the previous example:

Источник

Can we extend an enum in Java?

No, we cannot extend an enum in Java. Java enums can extend java.lang.Enum class implicitly, so enum types cannot extend another class.

Syntax

public abstract class Enum> implements Comparable, Serializable < // some statements >

Enum

  • An Enum type is a special data type which is added in Java 1.5 version.
  • An Enum is used to define a collection of constants, when we need a predefined list of values which do not represent some kind of numeric or textual data, we can use an enum.
  • Enums are constants and by default, they are static and final. so the names of an enum type fields are in uppercaseletters.
  • Public or protected modifiers can only be used with a top-level enum declaration, but all access modifiers can be used with nested enum declarations.

Example

enum Country < US < public String getCurrency() < return "DOLLAR"; >>, RUSSIA < public String getCurrency() < return "RUBLE"; >>, INDIA < public String getCurrency() < return "RUPEE"; >>; public abstract String getCurrency(); > public class ListCurrencyTest < public static void main(String[] args) < for (Country country : Country.values()) < System.out.println(country.getCurrency() + " is the currecny of " + country.name()); >> >

Output

DOLLAR is the currecny of US RUBLE is the currecny of RUSSIA RUPEE is the currecny of INDIA

Источник

Can Enum extend any class in java?

Enumeration (enum) in Java is a datatype which stores a set of constant values. You can use enumerations to store fixed values such as days in a week, months in a year etc.

Читайте также:  Python аргумент функции объект

You can define an enumeration using the keyword enum followed by the name of the enumeration as −

Just like arrays, the elements/constants in an enumeration are identified using numbers starting from 0 in the above example the days are identified using numbers as shown in the following illustration −

Enumerations are similar to classes and, you can have variables, methods and constructors within them. Only concrete methods are allowed in an enumeration.

Extending a class

All enumerations internally extend a class named Enum the base class of all the language enumeration types. Since Java doesn’t support multiple inheritance you cannot extend another class with enumeration if you try to do so, a compile time error will be generated.

Example

In the following java snippet we have a class with name Sample and we have created an Enum type named Scooters and tried to extend the Sample class.

import java.util.Scanner; class Sample < >enum Scooters extends Sample

Output

On executing, this class generates the following compile time error. D:\>javac EnumExample.java EnumExample.java:5: error: '', or ';' expected enum Scooters extends Sample< ^ 2 errors

Источник

Extend Enums in Java

Extend Enums in Java

This tutorial demonstrates how to extend the enum functionality in Java.

Extend enum in Java

We can consider enum as a kind of compiler magic because, in the byte code, the enum is represented as a class with several static members and is inherited from abstract java.lang.Enum .

It is the reason the enum cannot extend any other class or enum . As we cannot extend enum in Java, it is also impossible for any class to extend an enum . Let’s learn by using the following example code and see what happens.

package delftstack;  enum Cars Audi, BMW, Marcedes>  public class Example extends Cars    public static void main(String. args)    > > 

The code above has an enum named Cars , and class Example is trying to extend it. See output:

/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 

As we can see, the class cannot extend the enum . So if it is impossible to extend the enum , can we still extend its functionality?

The functionality can be defined as the implemented methods in the enum . For example, the enum Cars from the above code can declare abstract methods for each member; see the example:

enum Cars   Audi  @Override public void drive()  > >,  BMW  @Override public void drive()  > >,  Mercedes  @Override public void drive()  > >,  ;  public abstract void drive(); > 
  • If the enum belongs to a third-party library or another team, it will not allow to implementation of abstract methods.
  • If it belongs to the module which doesn’t have the dependency required for the drive() method.
  • If the enum is overloaded with other functions and data, it will be unreadable.

There are some solutions provided that can solve these problems and extend the functionality of enum in Java.

Solution 1: Mirror enum in Java

As the name suggests, we need to create another enum with the same data. That new enum will also implement the drive() method, So we have two enums now:

Example Code for enum Cars :

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

Example Code for enum DriveCars :

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

The second enum is the mirror of the first one. Now we can use both of these enums by extending the functionality; we need to use built-in enum methods that are name() and valueof() .

See the following example of how to use it:

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

The above code shows how enum Cars functionality is used in the enum DriveCars . Which means the functionality is extended.

The name() method in the above code is final , which cannot be overridden, and the valueOf method will be generated by the compiler. Both of these methods are a good fit for each other is there is no functional error in the extended operation.

There is one issue with the above code if the enum Cars is changed, the enum DriveCars will not have any idea, and it will cause the failure of the name and valueof trick. To solve this issue, we must let the DriveCars know that its parent mirror is Cars .

For that, we can use a static initializer to compare the DriveCars and Cars , which will throw the exception if both the enums do not match. Here is an example of that from the enumus library:

enum DriveCars   .  static   Mirror.of(Cars.class);  > > 

The utility class will check if both enums match or not. This method will validate the name() and valueOf() trick.

Solution 2: Map enum in Java

If you don’t want to create another enum that holds only one method. In this case, we can use interface instead of the enum ; see the example below:

public interface Driver   void drive(); > 

Now to use this interface Drive with the enum Cars , we can create a mapping between them. Here is the example for the map:

MapCars, 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()<>>) >> 

Now to use them, use this simple piece of code:

The EnumMap used in the code above will guarantee that each enum member will appear only once, but it does not guarantee an entry for each member.

We can check the size of the map is equal to the number of members of enums:

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

The enumus library also provides a utility for this case: if the map does not fit the Cars , it will throw the IllegalStateException . Here is the utility:

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

Both methods above show how to make enums powerful by extending their functionality. Though it is impossible to directly extend an enum , we can use these tricks to extend their functionalities.

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.

Related Article - Java Enum

Источник

Оцените статью