Предположим, у меня есть абстрактный класс Pipeline<T>
, который содержит некоторые элементы типа T
и реализующий класс IntPipeline
, который расширяет Pipeline<Integer>
.
abstract class Pipeline<T> {
abstract T getNextItem();
}
class IntPipeline extends Pipeline<Integer> {
Integer getNextItem() {
// generate integer here
return 0;
}
}
Теперь я хочунаписать несколько тестов.Поскольку все реализации Pipeline
будут иметь похожие тесты, я хочу создать абстрактный базовый класс для определения некоторых стандартных тестов:
abstract class PipelineTest<S, T extends Pipeline<S>> {
private final Class<T> clazz;
protected PipelineTest(Class<T> clazz) {
this.clazz = clazz;
}
abstract T createInstance();
@Test
void canBeSerializedAndDeserialzed() {
var serializer = ...;
T pipeline = createInstance();
var json = serializer.toJson(pipeline);
T deserializedPipeline = serializer.fromJson(json, clazz);
assertEquals(pipeline, deserializedPipeline);
}
}
Таким образом, конкретный тест будет выглядеть так:
class IntPipelineTest extends PipelineTest<Integer, IntPipeline> { // redundant information here
IntPipelineTest() {
super(IntPipeline.class);
}
IntPipeline createInstance() {
return new IntPipeline();
}
}
Как видите, когда я создаю конкретный тест, мне нужно передать туда избыточную информацию.Я говорю компилятору, что создам тест для конвейера типа Integer
.Насколько я понимаю, это может быть выведено из IntPipeline
.Поэтому я подозреваю, что с дженериками я делаю что-то в корне неправильное.
Так есть ли способ реструктурировать код, чтобы я мог создать тест без необходимости объявлять тип расширения Integer
?