Предположим, у вас есть следующий абстрактный класс Java:
public abstract class AbstractRequestHandler<I,O> {
I input;
O output;
}
и следующая иерархия дочерних классов:
public abstract class AbstractUserRequestHandler<I extends User,O> extends AbstractRequestHandler<I,O>{...}
public abstract class AbstractUniversityRequestHandler<I extends UniversityUser> extends AbstractUserRequestHandler<I,String>{...}
public class StudentRequestHandler extends AbstractUniversityRequestHandler<Student>{...}
public class TeacherRequestHandler extends AbstractUniversityRequestHandler<Teacher>{...}
Предположим, вам нужно использовать в заданной точке суперклассауниверсальный тип, например, чтобы десериализовать в конструкторе запрос json для конкретного объекта запроса с использованием библиотеки gson следующим образом:
public AbstractRequestHandler(final String inputJson) {
input = new Gson().fromJson(inputJson,typeOfI);
}
Вам необходим тип универсального I впеременная "typeOfI"
Существует ли глобальное решение, позволяющее получить универсальный тип, определенный конкретным дочерним классом, который учитывает следующие ограничения?
- тип получается во время выполнения независимо от иерархии дочерних классов (которая также может быть более сложной, чем приведенная в качестве примера по этому вопросу)
- Разработчику просто нужно определить универсальное расширение расширенного класса без указания вручную универсального типа где-то в конкретном дочернем классе (например, в переопределенном методе или конструкторе)
Так что, если вы хотите определить новый конкретный дочерний элемент, который назначит новое значение универсальному, вы можете просто написать следующий конкретный класс, например:
public class StudentRequestHandler extends AbstractUniversityRequestHandler<Student>{
public StudentRequestHandler(String inputJson) {
super(inputJson);
}
}
Я нашел следующие решения, но они не учитывают оба запрошенных ограничения решения.
Решение, которое нарушает ограничение n ° 2
Решением может быть определение абстрактного метода насуперкласс, как следует
protected abstract Type getRequestType();
, а затем реализовать его на каждом конкретном дочернем классе, который определяет универсальный:
public class StudentRequestHandler extends AbstractUniversityRequestHandler<Student>{
public StudentRequestHandler(String inputJson) {
super(inputJson);
}
@Override
protected Type getRequestType() {
return Student.class;
}
}
Тогда можно использовать метод getRequestType () on конструктор на целевом суперклассе:
public AbstractRequestHandler(final String inputJson) {
request = new Gson().fromJson(inputJson,getRequestType());
}
Но даже если он работает независимо от иерархии дочерних классов ( соблюдайте ограничение n ° 1 ), разработчик должен вручную реализовать абстрактный метод для каждого конкретногодочерний класс.
Решение, которое нарушает ограничение n ° 1
Если иерархия проста, имеет только прямой дочерний элемент, который простирается от целевого superclass , например:
public class TeacherRequestHandler extends AbstractRequestHandler<Teacher,String>{...}
@naikus (https://stackoverflow.com/users/306602/naikus) было предложено рабочее решение для следующего потока stackoverflow: Использование универсального типаподкласс внутри своего абстрактного суперкласса?
Однако это не сработает, если конкретный класс не является прямым потомком суперкласса, который определяет обобщенные значения (как тот, который предложен в качестве примерапо этому вопросу).