I came up with a solution that could work in your scenario, but it works a little bit differently than what you initially wanted to solve (the resolving of super
calls):
public class OpenInitialHandler extends InitialServerLegacyDelegate {
public OpenInitialHandler(BungeeCord bungee, ListenerInfo listener) {
super(bungee, listener);
}
public OpenInitialHandler(ProxyServer proxyServer, ListenerInfo listener) {
super(proxyServer, listener);
}
}
public class InitialServerLegacyDelegate /* implements and extends whatever you need */ {
private static final Constructor<InitialDelegate> targetConstructor = InitialServer.getConstructors()[0];
private final InitialServer delegate;
protected InitialServerLegacyDelegate(BungeeCord bungee, ListenerInfo listener) {
this(bungee, listener);
}
protected InitialServerLegacyDelegate(ProxyServer proxyServer, ListenerInfo listener) {
try {
// This is the critical part.
// Instead of binding/checking the constructor parameter types
// at compile-time, this will be resolved at runtime.
delegate = targetConstructor.newInstance(proxyServer, listener);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// implement all neccessary interface methods here
// and simply make them delegate methods
}
Essentially, the InitialServerLegacyDelegate
handles this legacy behaviour. It looks like a valid superclass (because it implements the same interfaces like InitialServer
, but in reality it just delegates all calls to an instance of InitialServer
which it resolves at runtime.
One problem you might be facing is: If your class gets a input at OpenInitialHandler(ProxyServer proxyServer, ListenerInfo listener)
where ProxyServer
is not of type BungeeCord
. In this case, the implementation will fail with a ClassCastException
if the newer dependency (with the BungeeCord
constructor) is present and it gets a non-BungeeCord
-input.
Delegate methods can easily be generated by Eclipse. For more detail, see this question on how to generate delegate methods in Eclipse.