Прежде всего, здесь есть только один класс Princess
, который является QueenA.Princess
. Нет QueenB.Princess
- если вы пишете QueenB.Princess
, то компилятор просто понимает это как QueenA.Princess
. Обратите внимание, что поскольку Princess
является нестационарным внутренним классом QueenA
, общий класс, QueenA.Princess
также является общим классом (параметризованным параметрами QueenA
). Когда он параметризуется, он выглядит как QueenA<something>.Princess
.
Поскольку проблема заключается в совместимости между двумя значениями класса Princess
, и что мы отметили выше, существует один такой класс, единственная проблема совместимости - это аргумент общего типа. Тип, который передается в super()
, предположительно Q.Princess
. Но, как мы отметили выше, Princess
относится к QueenA
, а не QueenB
или Q
. Поэтому компилятор во время компиляции автоматически переписывает это на QueenA<something>.Princess
. Вопрос в том, что такое something
. В принципе, вопрос: Q
- QueenA<what>
. Q
- это переменная типа с привязкой QueenB<?>
. Это означает, что кто-то может использовать этот класс с Q
, являющимся QueenB<X>
, причем X
является любым типом, который удовлетворяет границам параметра типа (а именно, который расширяет JokerB
). Поэтому мы ничего не можем предположить о X
, за исключением того, что это подтип JokerB
. QueenB<X>
распространяется QueenA<X>
, так что означает Q
- QueenA<X>
. <capture ...>
- это то, что компилятор печатает для обозначения неизвестного типа. Итак, на данный момент компилятор выяснил, что Q.Princess
действительно означает QueenA<some unknown type that extends JokerB>.Princess
.
Затем передайте его super()
, конструктору KingA
. Тип параметра для этого параметра также написан Q.Princess
(примечание: это Q
, параметр другого типа, не путайте). Если вы будете следовать тому же анализу, что и выше, вы увидите, что компилятор видит, что это Q.Princess
действительно означает QueenA<some unknown type that extends JokerA>.Princess
.
Вопрос QueenA<first unknown subtype>.Princess
Подтип QueenA<second unknown subtype>.Princess
? то есть first unknown subtype
то же, что и у second unknown subtype
? (Помните, что генерики являются инвариантными.) Компилятор, просто глядя на это, скажет, что он не знает, являются ли они одинаковыми или нет, потому что два неизвестных типа могут быть разными, поэтому они несовместимы.
Можно сказать, постойте, вы знаете, что Q
является QueenA<X>
для некоторого неизвестного типа X
, KingB<Q>
объявляется продлить KingA<Q>
, поэтому в Q
в рамках KingB
«s для конкретного объекта такой же, как Q
в области KingB
. Таким образом, Q
s одинаковы, а неизвестный X
в обоих случаях одинаковый. Но это не применяется здесь, потому что Q
больше не рассматривается. Помните, что нет типа Q.Princess
. Реальный тип - QueenA<something>.Princess
. Это QueenA<something>.Princess
вычисляется во время компиляции каждого конструктора для каждого класса. Как только выясняется, что это unknown type
, он затем фиксируется как unknown type
и не связан с Q
, который является параметром типа класса. Таким образом, два неизвестных типа не имеют отношения.
Вы можете решить эту проблему, используя новый параметр типа, вместо того чтобы позволить компилятору вывести неизвестный тип. Параметр type может затем позволить вам подключать отдельные виды использования, чтобы компилятор знал, что они одного типа. Что-то вроде этого:
abstract class KingA<J extends JokerA, Q extends QueenA<J>> {
KingA(Q.Princess princess) {
Gift giftForPrincess = new Gift();
princess.receiveGift(giftForPrincess);
}
}
abstract class KingB<J extends JokerB, Q extends QueenB<J>> extends KingA<J, Q> {
KingB(Q.Princess princess) {
super(princess);
}
}