1

I have this scenario

abstract class Notification<C extends Config> {
    private String text;
    private String title;
    private String topic;
    private C configuration;

    public C getConfig() {
        return configuration;
    }

    public void setConfig(C configuration) {
        this.configuration = configuration;
    }

    public String getText() {return text;}
    public void setText(String text) {this.text = text;}

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getTopic() {
        return topic;
    }

    public void setTopic(String topic) {
        this.topic = topic;
    }
}

class NotificationA extends Notification<ConfigA> {
    private Boolean notificationAccepted;

    public Boolean getNotificationAccepted() { 
        return notificationAccepted;
    }

    public void setNotificationAccepted(Boolean notificationAccepted) {
        this.notificationAccepted = notificationAccepted;
    }
}

class NotificationB extends Notification<ConfigB> {
    private LocalDate expirationDate;

    public LocalDate getExpirationDate() { 
        return expirationDate;
    }

    public void setExpirationDate(LocalDate expirationDate) {
        this.expirationDate = expirationDate;
    }
}

class NotificationC extends Notification<ConfigC> {
    private Boolean resend;

    public boolean resend() {return this.resend;}
    public void setResend(Boolean resend) {
        this.resend = resend;
    } 

    public LocalDate getExpirationDate() { 
        return expirationDate;
    }

    public void setExpirationDate(LocalDate expirationDate) {
        this.expirationDate = expirationDate;
    }
}

But this is causing me issues because I have to create Notifications depending on the Configuration I have, like this:

public Notification createNotification(Configuration configuration) {
    if(configuration instanceof ConfigurationA) {
        return new NotificationA();
    } else if (configuration instanceof ConfigurationB) {
        //...
    }
}

But then if I try to do this:

Notification notification = createNotification(configuration);
notification.setConfig(configuration); //Unchecked call to setConfig()!

As you can see, everything sucks here because I have to cast Notification again so the compiler does not complain about that unchecked call.

Can anyone please provide a better solution? I feel I have no way to fix this bad design.

If inheritance is not a good idea here then what should I do not to repeat code?

If this is not clear enough please kindly tell me what to fix in a comment. This is my first post on SO.

Martín
  • 19
  • 1
  • 1
    If the type of `Notification` depends on the type of `Config`, why don't you have the `Config` create the `Notification`? This is a [factory method pattern](https://en.wikipedia.org/wiki/Factory_method_pattern) and is commonly used. – Andreas Mar 02 '18 at 21:16
  • It's quite unclear why you need ConfigA, ConfigB and so on. And the generics too. This seems to me like a bad design from the start but there may be something in those Config classes that makes me wrong. – Ondřej Xicht Světlík Mar 02 '18 at 21:24
  • @Makoto According to the code, the OP doesn't use deliberately raw types for the part that causes a trouble. Generics are already used in the code. For this part he doesn't manage to. This general dup will probably not help him. – davidxxx Mar 02 '18 at 21:41
  • @davidxxx: `Notification` as declared above is being used as a raw type. The issue lies with the factory in creating them; he *has* to parameterize that class. The canonical explains that. – Makoto Mar 02 '18 at 21:43

2 Answers2

0

Give Configuration a createNotification<ConfigX>() method instead of the switch.

Or give Notification a constructor with the configuration instead of setting it.

Or a static factory method in each Notification subclass.

daniu
  • 14,137
  • 4
  • 32
  • 53
0

You can simple make createNotification() generic, like this:

public <T> Notification<T> createNotification(T config) {
    // ...
}

Then make it return the correct Notification generic type.

Charles Spencer
  • 626
  • 1
  • 6
  • 17
  • Thanks, but I tried this and I still get the "unchecked call" warning when I try to set the configuration since I can't do new Notification() since it's abstract. – Martín Mar 05 '18 at 13:05