Reputation: 8796
I have a base interface that is parameterized using a type R
extending the same base interface :
public interface IWidget<R extends IWidget<R>> {}
Then another interface is parameterized the same way :
public interface IWidgetManager<R extends IWidget<R>> {}
Finally, a class implements the second interface. This class will receive the IWidget
implementation class when it will be declared :
public class MyWidgetManager<R extends IWidget<R>> implements IWidgetManager<R> {}
My question :
What is the more specific type that we can use to specify MyWidgetManager
?
Class<?>
works, of course :
public Class<?> ok() {
return MyWidgetManager.class;
}
But it is very generic and I'd like something more specific...
Those attempts don't compile:
public Class<? extends IWidgetManager<?>> fails() {
return MyWidgetManager.class;
}
==> Type mismatch: cannot convert from Class<MyWidgetManager> to Class<? extends IWidgetManager<?>>
public <R extends IWidget<?>> Class<? extends IWidgetManager<R>> fails() {
return MyWidgetManager.class;
}
==> Type mismatch: cannot convert from Class<MyWidgetManager> to Class<? extends IWidgetManager<R>>
public <R extends IWidget<R>> Class<? extends IWidgetManager<R>> fails() {
return MyWidgetManager.class;
}
==> Type mismatch: cannot convert from Class<MyWidgetManager> to Class<? extends IWidgetManager<R>>
public Class<? extends IWidgetManager<? extends IWidget<?>>> fails() {
return MyWidgetManager.class;
}
==> Type mismatch: cannot convert from Class<MyWidgetManager> to Class<? extends IWidgetManager<? extends IWidget<?>>>
Is there any way I can get a type more specific than Class<?>
for MyWidgetManager.class
?
UPDATE : I changed the name of my interfaces. The final class is not a Widget itself, which wasn't clear in my original question... Sorry for the confusion.
UPDATE 2 :
Things are way easier when using concrete types, indeed.
This is really specific to my current situation, but I think I'll fix my "problem" by transforming MyWidgetManager<R extends IWidget<R>> implements IWidgetManager<R>
into a WidgetManagerBase
that doesn't implement anything. Then provide a default implementation with a concrete Widget class. Finally, the get method could be overriden easily (which is my main goal from the start, by the way!). So :
public interface IWidget<R extends IWidget<?>> {}
public interface IWidgetManager<R extends IWidget<R>> {}
public class WidgetManagerBase {}
// Default implementation
public class WidgetA implements IWidget<WidgetA> {}
public class AWidgetManager extends WidgetManagerBase implements IWidgetManager<WidgetA> {}
// default get method
public Class<? extends IWidgetManager<?>> getWidgetManagerClass() {
return AWidgetManager.class;
}
// The default get method then can be overriden with :
public class WidgetB implements IWidget<WidgetB> {}
public class BWidgetManager extends WidgetManagerBase implements IWidgetManager<WidgetB> {}
@Override
public Class<? extends IWidgetManager<?>> getWidgetManagerClass() {
return BWidgetManager.class;
}
Upvotes: 4
Views: 315
Reputation: 81539
I really think you're just looking for
public interface IBaseWidget<R extends IBaseWidget<R>> {}
and
public interface IWidget<R extends IWidget<R>> extends IBaseWidget<R> {} //not sure about this one.
and
public class MyWidget implements IWidget<MyWidget> {}
That way you can see MyWidget.class
as Class<R>
.
Is this what you are looking for, or do I misinterpret your intentions?
EDIT:
In that case,
public interface IWidgetManager<R extends IWidget<R>> {}
public class MyWidgetManager<R extends IWidget<R>> implements IWidgetManager<R> {}
could be replaced with
public interface IWidgetManager<R extends IWidget<R>, WM extends IWidgetManager<R, WM>> {}
public class MyWidgetManager<R extends IWidget<R>> implements IWidgetManager<R, MyWidgetManager> {}
because then you will be able to access MyWidgetManager.class
as Class<WM>
.
Upvotes: 2
Reputation: 25846
Because of Java Type Erasure the most specific match for MyWidget.class
is Class<? extends IWidget>
:
public Class<? extends IWidget> test() {
return MyWidget.class;
}
If you want to be even more specific than you should extend MyWidget with concrete type parameters:
public class ConcreteBaseWidget implements IBaseWidget<ConcreteBaseWidget> {
}
public class ConcreteWidget extends MyWidget<ConcreteBaseWidget> {
}
And then all these methods will work:
public Class<? extends IWidget<? extends IBaseWidget<? extends IBaseWidget<?>>>> test1() {
return ConcreteWidget.class;
}
public Class<? extends IWidget<? extends IBaseWidget<ConcreteBaseWidget>>> test2() {
return ConcreteWidget.class;
}
public Class<? extends IWidget<? extends ConcreteBaseWidget>> test3() {
return ConcreteWidget.class;
}
Upvotes: 3