gstackoverflow
gstackoverflow

Reputation: 37034

How to invoke enum value specific method outside of enum?

I have enum like this:

  public enum Email{
        WELCOME,
        LOGIN       
    }

EmailService has following method signature:

public void sendEmail(String from, String subject, String[] to, Map<String, String> props, String templateFileName)

I want to have API like this:

Email.WELCOME.send(from, subject, to, welcomeProp1, welcomeProp2....)



Email.LOGIN.send(from, subject, to, loginProp1, loginProp2....)

To acheve this I tried to add specific methods to enum fields:

public enum Email{
    WELCOME{
        public void send(String param1,String param2,String param3,String param4){
           ....    
        }
    },
    LOGIN{
        public void send(String anotherParam1,String anotherParam2,String anotherParam3){
            .... 
        }
    }
}

But I found out that I could not invoke this methods outside of enum. To acheve it I need to create abstract method and override in each enum value. But problem that signature of these methods are different and it is impossible to do it.

Any ideas?

Upvotes: 2

Views: 582

Answers (2)

Mykola Yashchenko
Mykola Yashchenko

Reputation: 5371

You can use polymorphism for in such case. First of all, define some interface, for instance:

public interface Message {
}

Then you should add an abstract method to the enum:

public abstract void send(Message message);

After that, create two child classes - the first one is for WELCOME and the second one is for LOGIN:

class WelcomeMessage implements Message {
    private String param1;
    private String param2;
    private String param3;
    private String param4;

    // constructor, getters
}

class LoginMessage implements Message {
    private String anotherParam1; 
    private String anotherParam2; 
    private String anotherParam3;

    // constructor, getters
}

Then add implementations of send() method:

public enum Email {
    WELCOME {
        public void send(Message message) {
            WelcomeMessage wm = (WelcomeMessage) message;
            ....    
        }
    },
    LOGIN {
        public void send(Message message) {
            LoginMessage lm = (LoginMessage) message;
            .... 
        }
    }
}

UPD. @gstackoverflow mentioned that it's possible to invoke methods with "incorrect" implementation. I guess I know how to prevent this.

public enum Email {
    WELCOME {
        protected void sendInternal(Message message) {
            WelcomeMessage wm = (WelcomeMessage) message;
            ....    
        }

        protected Class<? extends Message> getSupportedClass() {
            return WelcomeMessage.class;
        }
    },
    LOGIN {
        protected void sendInternal(Message message) {
            LoginMessage lm = (LoginMessage) message;
            .... 
        }

        protected Class<? extends Message> getSupportedClass() {
            return LoginMessage;
        }
    };

    public static void send(Message message) {
        for (Email email : values()) {
            if (email.getSupportedClass().equals(message.getClass()) {
                email.sendInternal(message);
            }
        }
    }
    protected abstract void sendInternal(Message message);
    protected abstract Class<? extends Message> getSupportedClass();
}

Upvotes: 1

OldCurmudgeon
OldCurmudgeon

Reputation: 65811

One solution is to make all the methods take exactly the same object, they just use different parameters from it.

class EmailDetails {
    String param1;
    String param2;
    String param3;
    String param4;
    String anotherParam1; 
    String anotherParam2; 
    String anotherParam3;
}

public enum Email {
    WELCOME {
        public void send(EmailDetails details) {
            System.out.println("Welcome!!");
        }
    },
    LOGIN {
        public void send(EmailDetails details) {
            System.out.println("Log in!!");
        }
    };

    public abstract void send(EmailDetails details);
}

public void test(String[] args) {
    Email.WELCOME.send(new EmailDetails());
    Email.LOGIN.send(new EmailDetails());
}

You will generally find that many of the fields are common to all uses.

Upvotes: 1

Related Questions