What I want is following:
Most of the time, the generic class will be like TestBuilder<X, X>
, meaning that T and O are of the same type. Therefore I create two different constructor. I want to make anonoumous new calls like new TestBuilder<>(...)
(I'm calling the <>
anonoumous here).
Following 4 constructor example exists:
1) Working constructor calls
// Anonoumous, working
new TestBuilder<>(String.class, Integer.class)
.withOnNext(new Action1<Integer>()
{
@Override
public void call(Integer integer)
{
}
});
// not anonoumous, classified, working
new TestBuilder<String, String>(String.class)
.withOnNext(new Action1<String>()
{
@Override
public void call(String string)
{
}
});
2) Constructor Calls with problems or not working
// Anonoumous and working
// PROBLEM: withOnNext is called with Object instead of String
new TestBuilder<>(String.class)
.withOnNext(new Action1<Object>()
{
@Override
public void call(Object o)
{
}
});
// Anonoumous and NOT working
// this is what I want to work!
new TestBuilder<>(String.class)
.withOnNext(new Action1<String>()
{
@Override
public void call(String string)
{
}
});
Question
Is there a way to get the 4th constructor to work? I don't want to be forced to give the constuctor two classes if I call it with one argument only, the second generic class should "inherit" from the first in this case... Instead of having to write new TestBuilder<String, String>(String.class)
I want to write new TestBuilder<>(String.class)
or at least new TestBuilder<String>(String.class)
...
Class
This is what the test builder class looks like:
public class TestBuilder<T, O>
{
public TestBuilder(Class<T> eventClass)
{
this(eventClass, (Class<O>)eventClass);
}
private TestBuilder(Class<T> eventClass, Class<O> observableClass)
{
init();
}
public TestBuilder<T, O> withOnNext(Action1<O> actionNext)
{
mActionNext = actionNext;
return this;
}
}
I don't think Java can infer the second generic type without some kind of hint. One way is giving the type in variable declaration:
TestBuilder<String, String> testBuilder = new TestBuilder<>(String.class);
testBuilder.withOnNext(new Action1<String>() {
@Override
public void call(String string) {
//...
}
});
But you'd still need to declare both generic parameters.
What I would do is encapsulating the information that both T
and O
are the same in a static factory method:
public class TestBuilder<T, O> {
public static <T> TestBuilder<T, T> create(Class<T> eventClass) {
return new TestBuilder<T, T>(eventClass);
}
// ...
}
and then call it like this:
TestBuilder.create(String.class).withOnNext(...);
Yet another option is encapsulating the information in a separate class inheriting from TestBuilder
:
public class SimpleTestBuilder<T> extends TestBuilder<T,T> {
public SimpleTestBuilder(Class<T> eventClass) {
super(eventClass, eventClass);
}
}
public class TestBuilder<T, O> {
private TestBuilder(Class<T> eventClass, Class<O> observableClass) {
}
// ...
}
Used as
new SimpleTestBuilder<>(String.class).withOnNext(...);
Yet another good option is to encapsulate the information O
is same as T
in a static method:
public class TestBuilder<T, O> {
public static <T> TestBuilder<T, T> create(Class<T> eventClass) {
return new TestBuilder<T, T>(eventClass);
}
// ...
}
Used as
TestBuilder.create(String.class).withOnNext(...);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With