Reputation: 37034
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
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
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