Невозможно сделать это во время компиляции.
Если вы действительно хотите, вы можете принудительно применить его во время выполнения (предотвращая создание экземпляров классов c), добавив logi c в неперсональный конструктор A
:
protected A(T t) {
validateClass(getClass());
this.t = t;
}
private static void validateClass(final Class<?> clazz) {
final Type superclass = clazz.getGenericSuperclass();
if ((superclass instanceof ParameterizedType)
&& ((ParameterizedType)superclass).getRawType() == A.class
&& ((ParameterizedType)superclass)getActualTypeArguments()[0] == clazz
) {
// OK
} else {
throw new IllegalStateException(
clazz + " does not extend A<" + class.getName() + ">");
}
}
. . . но я не думаю, что это отличная идея.
В целом, хотя Java предоставляет множество функций для защиты во время компиляции, программа Java в конечном итоге полагается на разработчиков, которые добровольно пишут правильный код. Многие аспекты контрактов классов задокументированы, но не применяются. (Например, ничто не заставляет методы hashCode()
и equals()
согласовываться друг с другом; но если вы пишете код Java, вы прочтете документацию по этим методам, прежде чем переопределить их, чтобы знать, что вам нужно это сделать.) В вашем случае вам лучше просто сказать разработчикам, что подклассы A
должны передавать себя в качестве аргумента типа A
, дав им пример и доверив им это сделать.