I get this compile error "required T, found UseCaseTest" when I try to return INSTANCE at the method keepStateBetweenTests of the class UseCaseTest. I know I can easily fix it casting to T, but I want to do it right.
Plus, I don't know why the line
if (INSTANCE == null) INSTANCE = getInstance(activityTestRule);
can compile, given the previous error.
I supply two more classes to provide certain context.
UseCaseTest
public abstract class UseCaseTest {
private static UseCaseTest INSTANCE;
public abstract static class Builder<T extends UseCaseTest> {
private final ActivityTestRule activityTestRule;
protected Builder(ActivityTestRule activityTestRule) {
this.activityTestRule = activityTestRule;
}
public T keepStateBetweenTests() {
if (INSTANCE == null) INSTANCE = getInstance(activityTestRule);
return INSTANCE; //compile error: required T, found UseCaseTest
}
public T releaseStateBetweenTests() {
return getInstance(activityTestRule);
}
protected abstract T getInstance(ActivityTestRule activityTestRule);
}
private final ActivityTestRule activityTestRule;
public UseCaseTest(ActivityTestRule activityTestRule) {
this.activityTestRule = activityTestRule;
}
}
SessionUseCaseTest
public final class SessionUseCaseTest extends UseCaseTest {
public static Builder<SessionUseCaseTest> with(ActivityTestRule activityTestRule) {
return new Builder<SessionUseCaseTest> (activityTestRule) {
@Override protected SessionUseCaseTest getInstance(ActivityTestRule activityTestRule) {
return new SessionUseCaseTest(activityTestRule);
}
};
}
private SessionUseCaseTest(ActivityTestRule activityTestRule) {
super(activityTestRule);
}
public void signUp() {}
public void logout() {}
}
SessionTest
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SessionTest extends BaseTest {
@Test public void _1_SingUp() {
SessionUseCaseTest.with(mActivityRule)
.keepStateBetweenTests()
.signUp();
}
@Test public void _2_Logout() {
SessionUseCaseTest.with(mActivityRule)
.keepStateBetweenTests()
.logout();
}
}
The topic of static method/fields in conjunction with generics is very well described in this post
Nevertheless, it would seem a simple casting makes the compiler happy while allowing to keep some level of generics in place:
public T keepStateBetweenTests() {
if (INSTANCE == null)
INSTANCE = getInstance(activityTestRule);
return (T)INSTANCE;
}
UPDATE
Part of your question was why this can compile although there is the error:
if (INSTANCE == null) INSTANCE = getInstance(activityTestRule);
To my understanding, the compiler knows the INSTANCE itself is actually UseCaseTest, which fulfills the restriction defined on the Builder class: <T extends UseCaseTest>
You need to make your class aware of type T i.e.
public abstract class UseCaseTest <T> {
You can do like below:-
class UseCaseTest<T> {
final Class<T> useCaseTestType;
public UseCaseTest(Class<T> useCaseTestType) {
this.useCaseTestType = useCaseTestType;
}
//Then write your methods which are generic
}
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