通过将新类型指定为generics的实际类型来扩展generics有什么好处

我在某处看到了这种模式:

class A extends B { } 

通过将新类型指定为generics的实际类型,此结构对于扩展generics有点不寻常。 有什么用? 这个模式有名字吗? 有没有替代模式?

示例: https : //code.google.com/p/selenium/wiki/LoadableComponent

跳转到: public class EditIssue extends LoadableComponent {

编辑:阅读完回复后,我似乎需要改变编译器对类型检查的理解。 在我的脑海里,我的牛肉有这种模式,如果两个A需要相同,那么有没有办法不重复它们? 但似乎没有更好的方法将派生类的类型传播给父类。

在处理递归数据结构时,您可能会执行类似的操作。 例如,图形或树中的节点可以定义为其他节点的集合:

 class Node extends AbstractList { ... } 

同样,如果抽象/generics类型用于比较类似类型的对象,您可能会看到类似这样的内容,例如java.lang.Comparable

 class MyObject implements Comparable { public int compareTo(MyObject other) { ... } } 

举个例子:

 E extends Comparable 

这意味着E必须是一个知道如何与自身进行比较的类型,因此,递归类型定义。

不知道它是否有任何官方名称,但我会称之为递归generics模式

此模式与任何其他子类相同。 使用generics时真正发生的事情是JVM正在创建一个类的副本(实际上不是副本,但它有点类似),并用指定的类型替换generics使用的所有点。

所以,为了回答你的问题,所有这种模式都在用B代替B ,其中A所有用途都被A类所取代。 这种情况的潜在用途是您为特定类定制数据结构(来自java.util.Collections ),例如使用bitshifts将Collection压缩为较小的内存量。 我希望这是有道理的!

这确实令人困惑,因为AB两种类型似乎依赖于彼此存在; 在普通的OOP中没有多大意义,那么它的用途是什么? 我发现了这种模式的3个用例。

作文转为inheritance

假设一个Node 有一个子节点列表。 通常的设计是通过构图

 class Node ArrayList children = ... 

有时为了获得较小的性能,人们会使用inheritance

 class Node extends ArrayList // the super class represents the children... 

这有点令人困惑,但没有什么难以理解的。 我们知道这只是一种方便,它并不试图传达一个节点是一个节点列表。

可以考虑LoadableComponent这个用例。 它可以说是一种不太理想的设计而不是合成方法

 class ComponentLoader C get(){...} class EditIssue final ComponentLoader loader = new ComponentLoader(){ @Override void load(){...} @Override void isLoaded(){...} }; EditIssue compo = ... compo.loader.get().doSomething(); 

设计师可能会发现这种方法更具锅炉性。

方法链接

而不是写作

 foo.doA(); foo.doB(); 

很多人宁愿写作

 foo.doA().doB(); 

不幸的是,该语言并不直接支持方法链,即使它正在成为越来越渴望的function。 解决方法是让doA()返回foo 。 它有点脏但可以接受。

但是,如果foo位于类型层次结构中,则解决方法将被破坏

 class Bar Bar doA() class Foo extends Bar Foo doB(); foo.doA().doB(); // doesn't compile, since doA() returns Bar 

所以有些人要求一种特殊的“自我型”来解决这个问题。 假设有一个关键字This代表“自我类型”

 class Bar This doA() foo.doA().doB(); // works, doA() returns the type of foo, which is Foo 

看来方法链是“自我类型”的唯一用例,所以语言可能永远不会引入它(最好只支持方法链接)

人们发现generics为这个问题提供了一种解决方法

 class Bar This doA() class Foo extends Bar Foo has a method "Foo doA()", inherited from Bar 

这是A extends B模式最常用的用例。 这是一个孤立的解决方法/技巧。 它在A和B之间的关系中没有添加语义。

约束This也是一种流行的做法

 class Bar> 

这是丑陋和无用的,我强烈建议反对它。 只需使用“This”作为约定来表明它的用途。

LoadableComponent也可以归入此用例。 在更简单的设计中我们可以做到

 class LoadableComponent void ensureLoaded() class EditIssue extends LoadableComponent EditIssue compo = ... compo.ensureLoaded(); compo.doSomething(); 

为了支持最后两行的方法链接, LoadableComponent以其当前forms设计,以便我们可以编写compo.get().doSomething()

更多的东西

所以前两个用例是一种黑客攻击。 如果AB之间存在真正的约束怎么办?

而不是作为普通超类型, B更多元,它描述了类型A应该具有引用A本身的一些属性。 这不是传统OOP的inheritance,它更抽象。 (虽然它仍然通过传统的inheritance机制实现,但可以想象该语言可以将其作为一个独立的概念来推广。)

这个用例是Comparable的。 它描述了某种类型可以与自身进行比较。 由于它不是传统的OOP类型,理想情况下我们不应该声明具有静态类型Comparable的对象。 我们在公共方法返回/参数类型中看不到它,它没有多大意义。 相反,我们看到的东西

 > void sort(List) 

这里的方法需要一个符合Comparable模式的类型。

(我真的不知道我在这节谈论的是什么)