0

I have following classes:

public class A extends Exception {
}

public class B extends Email {

}

My goal is to implement some strategy that would be able to work with both those classes like below:

For instance:

public enum Strategy {
    ACTION_1 {

        @Override
        public void handleAction(Class<? extends Exception > parameterThatShouldAcceptOnlyA) {
            throw parameterThatShouldAcceptOnlyA;
        }
    },
    ACTION_2 {

        @Override
        public void handleAction(Class<? extends Email > parameterThatShouldAcceptOnlyB) {
            parameterThatShouldAcceptOnlyB.send();
        }
    };

    public abstract void handleAction(Class<?> parameterThatShouldAcceptBoth);
}

This is not compiled through incorrect generic in overriden methods.

Could you please suggest how it would be possible to make this workable?

Harmlezz
  • 7,972
  • 27
  • 35
fashuser
  • 2,152
  • 3
  • 29
  • 51
  • Are you planning on calling `ACTION_1.handleAction(...)`, or `someDynamicStrategy.handleAction(...)`? – shmosel May 17 '17 at 07:15
  • Clearly the problem is that you're using `Class` type. This type does not represents an object of type `T`, but meta information associated to a Java class. The other problem, is that you're try to generify an `enum`, which is not possible. Try to define a `Strategy` interface instead. – riccardo.cardin May 17 '17 at 07:22

2 Answers2

2

You better step back here. Your idea simply violates the Liskov Substitution Principle.

Basically you want to restrict a subclass in what can be passed in as argument to a method.

That breaks the whole idea that subclasses can be used in place of their superclass. Because now, all of a sudden, the code that wants to call that method has to check the type of the object it is calling on - to ensure to not call the method with "invalid" parameters.

In other words: take this compiler error as a symptom. Even when you somehow work around the specific issue; as said - you better step back and rethink your whole idea.

Community
  • 1
  • 1
GhostCat
  • 137,827
  • 25
  • 176
  • 248
1

Hint: It is neither possible to throw a Class instance nor to invoke other methods than provided by class Class so at first you need to change your parameter type. This also let you remove the wildcards.

You can define the super class by a generic. Unfortunatelly enums do not support generics. But you can create a generic interface like

interface Handler<T> {
    void handleAction(T t);
}

and implement your handler like

class EmailHandler implements Handler<Email> {
    void handleAction(Email email) {
        email.send();
    }

class ExceptionHandler implements Handler<Exception> {
    void handleAction(Exception e) {
        // Exception is a checked exception
        // so we cannot throw it without 'throws' declaration
        // but we cannt add 'throws Exception'
        if (e instanceof RuntimeException)
            throw (RuntimeException) e;
        else
            throw new RuntimeException("wrapped", e);
    }
Stefan Warminski
  • 1,845
  • 1
  • 9
  • 18