Implement an interface with a method signature whose generic parameters extend an interface
Solution 1:
The way the interfaces are defined, you cannot override the method and change its signature, even if LibraryCalculator
is a subtype of GenericCalculator
. The other answer explains why.
One way to solve that is to parameterize the GenericRunner
interface with the calculator type:
public interface GenericRunner<T, A, C extends GenericCalculator<T, A>> {
T run(C calculator);
}
public class LibraryRunner<T> implements GenericRunner<T, LibraryAlgorithm, LibraryCalculator<T>> {
@Override
public T run(LibraryCalculator<T> calculator) {
...
}
}
But note that you cannot return an Object
in the LibraryRunner
method, as it does not match T
. If you want to return a specific type like Object
(which defeats the purpose of the generic LibraryCalculator
), you have to specify it explicitly:
public class LibraryRunner implements GenericRunner<Object, LibraryAlgorithm, LibraryCalculator<Object>> {
@Override
public Object run(LibraryCalculator<Object> calculator) {
return new Object();
}
}
If that's not what you want, then it's up to the user of LibraryRunner
to decide which type T
should be bound to.
Solution 2:
When you override a method or implement it, you always need to satisfy the condition of the overridden method, for example you should still be able to call LibraryRunner.run with a parameter GenericCalculator. else it wont make sense to write:
LibraryRunner libRunner = new LibraryRunner();
GenericRunner genRunner = libRunner;
genRunner.run(new GenericCalculator<>());
Overriding the exception does work because when you call GenericCalculator.calc
you are expecting any exception and calling LibraryCalculator.calc
narrow it down to only LibraryException
.
you can look on overriding methods as promise more information.