Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shared methods between enums

Tags:

java

enums

groovy

I want to refactor an emun in two new enums, but I don't like to copy/paste the enum methods in all new enums.

enum EmailType {
    REMINDER_ADMIN('reminderForAdmin')
    REMINDER_PRODUCTION('reminderForProduction')
    REMINDER_MANAGEMENT('reminderForManagement')
    REMINDER_CUSTOMER('reminderForCustomer')

    private final propertiesIdentifier

    String getTemplate(type) {
        ...
    }

    String getFrom(type) {
        ...
    }

    String getTo(type) {
        ...
    }

    String getBcc(type) {
        ...
    }

    ...
}

It's possible to implements only one time the methods and use in several enums?

enum EmailTypeAdministration {
    REMINDER_ADMIN('reminderForAdmin')
    REMINDER_PRODUCTION('reminderForProduction')

    ...
}

enum EmailTypeClients {
    REMINDER_MANAGEMENT('reminderForManagement')
    REMINDER_CUSTOMER('reminderForCustomer')

    ...
}
like image 270
Arturo Herrero Avatar asked Nov 21 '11 10:11

Arturo Herrero


People also ask

Can you have methods in enums?

The enum class body can include methods and other fields. The compiler automatically adds some special methods when it creates an enum. For example, they have a static values method that returns an array containing all of the values of the enum in the order they are declared.

Can enums have public methods?

An enum can, just like a class , have attributes and methods. The only difference is that enum constants are public , static and final (unchangeable - cannot be overridden).

Can enums have user defined methods?

Below code uses enums with defined methods: We should define methods as abstract methods and then we have to implement defferent flavours/logic based on each enum members. Because of declaring abstract method at the enum level; all of the enum members require to implement the method.

Can you use == on enums?

Because there is only one instance of each enum constant, it is permissible to use the == operator in place of the equals method when comparing two object references if it is known that at least one of them refers to an enum constant.


3 Answers

As my old friend Clippy would say, "it looks like you're using Groovy". If so, you can use a mixin to add the common methods to both enums.

// This class holds the methods that will be mixed-in to the enums
class EnumUtils {
    String getTemplate(type) {
      "template" + type       
    }

    String getFrom(type) {        
    }

    String getTo(type) {        
    }

    String getBcc(type) {        
    }
}

// This annotation adds the common methods to the enum
@Mixin(EnumUtils)
enum EmailTypeAdministration {
    REMINDER_ADMIN('reminderForAdmin'),
    REMINDER_PRODUCTION('reminderForProduction')

   EmailTypeAdministration(str) {} 
}

// This annotation adds the common methods to the enum
@Mixin(EnumUtils) 
enum EmailTypeClients {
    REMINDER_MANAGEMENT('reminderForManagement'),
    REMINDER_CUSTOMER('reminderForCustomer')

   EmailTypeClients(str) {}
}

// Quick test to prove the methods exist and return the expected values 
EmailTypeAdministration emailTypeAdmin = EmailTypeAdministration.REMINDER_ADMIN
assert 'templateParam' == emailTypeAdmin.getTemplate('Param')

You can run the code above in the Groovy console to prove it works as advertised

like image 109
Dónal Avatar answered Oct 07 '22 10:10

Dónal


Enums cannot extend any other class since all enums automatically extend class named Enum. So, your only option is to delegate the methods implementation to separate utility. This may be relevant if the implementation is not trivial (more than one line). Otherwise delegation does not give you serious benefits.

Other possibility is to extend Enum manually but I be ready to write verbose code like valueOf(), values() etc., so I am not sure you really need this.

EDIT:

Take a look on my article about Hierarchical Enums. It can probably help you too.

like image 20
AlexR Avatar answered Oct 07 '22 12:10

AlexR


Finally the Mixin solution don't works because @Mixin annotation only works with classes instead of enums.

I use a similar approach with delegate. Delegate transformation works fine! This code can be improve to use EnumUtils with factory or singleton pattern.

class EnumUtils {
    String getTemplate(type) {
      "template" + type       
    }

    String getFrom(type) {        
    }

    String getTo(type) {        
    }

    String getBcc(type) {        
    }
}

enum EmailTypeAdministration {
    REMINDER_ADMIN('reminderForAdmin'),
    REMINDER_PRODUCTION('reminderForProduction')

    @Delegate EnumUtils enumUtils = new EnumUtils()
    EmailTypeAdministration(str) {} 
}

enum EmailTypeClients {
    REMINDER_MANAGEMENT('reminderForManagement'),
    REMINDER_CUSTOMER('reminderForCustomer')

    @Delegate EnumUtils enumUtils = new EnumUtils()
    EmailTypeClients(str) {}
}

EmailTypeAdministration emailTypeAdmin = EmailTypeAdministration.REMINDER_ADMIN
assert 'templateParam' == emailTypeAdmin.getTemplate('Param')
like image 2
Arturo Herrero Avatar answered Oct 07 '22 10:10

Arturo Herrero