Использование универсального типа любого вложенного подкласса в его абстрактном суперклассе - PullRequest
0 голосов
/ 08 декабря 2018

Предположим, у вас есть следующий абстрактный класс 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"

Существует ли глобальное решение, позволяющее получить универсальный тип, определенный конкретным дочерним классом, который учитывает следующие ограничения?

  1. тип получается во время выполнения независимо от иерархии дочерних классов (которая также может быть более сложной, чем приведенная в качестве примера по этому вопросу)
  2. Разработчику просто нужно определить универсальное расширение расширенного класса без указания вручную универсального типа где-то в конкретном дочернем классе (например, в переопределенном методе или конструкторе)

Так что, если вы хотите определить новый конкретный дочерний элемент, который назначит новое значение универсальному, вы можете просто написать следующий конкретный класс, например:

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: Использование универсального типаподкласс внутри своего абстрактного суперкласса?

Однако это не сработает, если конкретный класс не является прямым потомком суперкласса, который определяет обобщенные значения (как тот, который предложен в качестве примерапо этому вопросу).

1 Ответ

0 голосов
/ 10 декабря 2018

Вы не можете получить универсальный параметр без наследования, потому что универсальные значения в java имеют тип стирания: https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

Вам необходимо использовать подход, которым вы поделились в своем вопросе.Использование наследования и ParameterizedType:

(Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...