嵌套在泛型中的 class 的泛型使用
Generic use of a class nested in a generic
即使这不是一个好的做法,我也想知道是为了知道为什么。
下面的代码无法编译,我不太明白为什么。
假设我有一个小丑、女王和国王的抽象定义:
abstract class JokerA {
//JokerA does things
}
abstract class QueenA<J extends JokerA> {
//QueenA makes use of J
class Princess {
void receiveGift(Gift gift) {
/* ... */
}
}
}
abstract class KingA<Q extends QueenA<?>> {
KingA(Q.Princess princess) {
Gift giftForPrincess = new Gift();
princess.receiveGift(giftForPrincess);
}
}
这很好用。
不过,我也想定义一个比较专业,但还是比较抽象的,Joker, Queen and King
abstract class JokerB extends JokerA {
//JokerB does some things differently
}
abstract class QueenB<J extends JokerB> extends QueenA<J> {
//QueenB makes use of J sometimes differently, because she knows how JokerBs behave
}
abstract class KingB<Q extends QueenB<?>> extends KingA<Q> {
KingB(Q.Princess princess) {
super(princess); //error
}
}
错误是:
KingA(QueenA<capture<?>>.Princess) in KingA cannot be applied to (Q.Princess)
但是,我看不出公主 class 会有什么不同。
谁能教教我?
首先这里只有一个class名字叫Princess
,就是QueenA.Princess
。没有 QueenB.Princess
——如果你写 QueenB.Princess
,编译器会简单地将其理解为 QueenA.Princess
。请注意,由于 Princess
是 QueenA
的非静态内部 class,泛型 class,QueenA.Princess
也是泛型 class(参数化通过 QueenA
的参数)。当它被参数化时,它看起来像 QueenA<something>.Princess
.
由于问题是 class Princess
的两个值之间的兼容性,而我们在上面注意到有一个这样的 class,唯一的兼容性问题是关于通用的类型参数。传递给 super()
的类型应该是 Q.Princess
。但是正如我们上面提到的,Princess
属于 QueenA
,而不是 QueenB
或 Q
。所以编译器在编译时会自动将其重写为 QueenA<something>.Princess
。问题是什么是something
。基本上,问题是 Q
是一个 QueenA<what>
。 Q
是一个绑定 QueenB<?>
的类型变量。这意味着有人可以使用此 class,Q
是 QueenB<X>
,X
是满足 QueenB
类型参数边界的任何类型(即扩展 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
(注意:这是KingA
的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
是某个未知类型 X
的 QueenA<X>
,KingB<Q>
被声明为扩展 KingA<Q>
,因此 KingB
范围内特定对象的 Q
与 KingB
范围内的 Q
相同。所以 Q
是相同的,未知的 X
在两种情况下都是相同的。但这在这里不适用,因为 Q
不再被考虑。请记住,没有类型 Q.Princess
。它表示的真实类型是QueenA<something>.Princess
。 QueenA<something>.Princess
是在编译时为每个 class 编译每个构造函数时计算出来的。一旦计算出是 unknown type
,它就固定为 unknown type
,并且与 class 的类型参数 Q
无关。所以这两个未知类型没有关系。
您可以通过使用新类型参数而不是让编译器推断未知类型来解决它。然后,类型参数可以让您连接该类型的不同用途,让编译器知道它们是同一类型。像这样:
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);
}
}
即使这不是一个好的做法,我也想知道是为了知道为什么。
下面的代码无法编译,我不太明白为什么。
假设我有一个小丑、女王和国王的抽象定义:
abstract class JokerA {
//JokerA does things
}
abstract class QueenA<J extends JokerA> {
//QueenA makes use of J
class Princess {
void receiveGift(Gift gift) {
/* ... */
}
}
}
abstract class KingA<Q extends QueenA<?>> {
KingA(Q.Princess princess) {
Gift giftForPrincess = new Gift();
princess.receiveGift(giftForPrincess);
}
}
这很好用。 不过,我也想定义一个比较专业,但还是比较抽象的,Joker, Queen and King
abstract class JokerB extends JokerA {
//JokerB does some things differently
}
abstract class QueenB<J extends JokerB> extends QueenA<J> {
//QueenB makes use of J sometimes differently, because she knows how JokerBs behave
}
abstract class KingB<Q extends QueenB<?>> extends KingA<Q> {
KingB(Q.Princess princess) {
super(princess); //error
}
}
错误是:
KingA(QueenA<capture<?>>.Princess) in KingA cannot be applied to (Q.Princess)
但是,我看不出公主 class 会有什么不同。
谁能教教我?
首先这里只有一个class名字叫Princess
,就是QueenA.Princess
。没有 QueenB.Princess
——如果你写 QueenB.Princess
,编译器会简单地将其理解为 QueenA.Princess
。请注意,由于 Princess
是 QueenA
的非静态内部 class,泛型 class,QueenA.Princess
也是泛型 class(参数化通过 QueenA
的参数)。当它被参数化时,它看起来像 QueenA<something>.Princess
.
由于问题是 class Princess
的两个值之间的兼容性,而我们在上面注意到有一个这样的 class,唯一的兼容性问题是关于通用的类型参数。传递给 super()
的类型应该是 Q.Princess
。但是正如我们上面提到的,Princess
属于 QueenA
,而不是 QueenB
或 Q
。所以编译器在编译时会自动将其重写为 QueenA<something>.Princess
。问题是什么是something
。基本上,问题是 Q
是一个 QueenA<what>
。 Q
是一个绑定 QueenB<?>
的类型变量。这意味着有人可以使用此 class,Q
是 QueenB<X>
,X
是满足 QueenB
类型参数边界的任何类型(即扩展 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
(注意:这是KingA
的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
是某个未知类型 X
的 QueenA<X>
,KingB<Q>
被声明为扩展 KingA<Q>
,因此 KingB
范围内特定对象的 Q
与 KingB
范围内的 Q
相同。所以 Q
是相同的,未知的 X
在两种情况下都是相同的。但这在这里不适用,因为 Q
不再被考虑。请记住,没有类型 Q.Princess
。它表示的真实类型是QueenA<something>.Princess
。 QueenA<something>.Princess
是在编译时为每个 class 编译每个构造函数时计算出来的。一旦计算出是 unknown type
,它就固定为 unknown type
,并且与 class 的类型参数 Q
无关。所以这两个未知类型没有关系。
您可以通过使用新类型参数而不是让编译器推断未知类型来解决它。然后,类型参数可以让您连接该类型的不同用途,让编译器知道它们是同一类型。像这样:
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);
}
}