5

有人可以解释以下相当复杂的递归通用模板用法吗?

public abstract class Data<E extends Data<E, S>,
                           S extends Writer<E>> extends Entity<E,S>

在使用递归泛型时我们应该记住什么,就像上面一样。这些类型之间的关系和规则如何,这里是E & S

如果有的话,请提供一些关于这种通用用法的资源/链接/书籍。我知道一本书在谈论这个,Effective Java,Joshua Bloch 的第二版(第 27 条)

4

3 回答 3

3

让我们从最简单的开始

S extends Writer<E>

任何类型 S 的类都必须是类 E 的编写者

extends Entity<E,S>

这里只是继承,Data 类扩展了 Entity 类。

E extends Data<E, S>

用于 E 的任何类本身都必须继承自 Data 类,并使用其自己的类型和与自身兼容的编写器继承/实现 Data 的泛型方法。

E & S 之间的关系应该是这样的:

//E = Example, S = ExampleWriter
public class ExampleWriter implements Writer<Example>{
//...
}
public class Example extends Data<Example,ExampleWriter>{
//...
}

请记住:泛型提供一个Writer<SomeChildOfExample>或一个Writer<SomeParentOfExample>可能会或可能不会创建编译器错误,这取决于在两种泛型类型中定义的泛型方法。

于 2011-01-11T13:52:12.470 回答
2

Data有两个参数,E它们最终必须是它自己的一个实例,并且S它必须能够成为Writer它自己的一个实例(更具体地说,是由 指定的同一种自身实例E)。最后,Data<E,S>还限定为/继承Entity由相同E和参数化的能力S(即,Entity属于Data<E,S>Writer<E>)。

具体的实现可能看起来像

NumericalData extends Data<NumericalData, NumWriter>whereNumWriter实现/扩展Writer<NumericalData>并且NumericalData也有资格作为Entity<NumericalData, NumWriter>.

编辑:

为什么要做这样的事情?有人可能希望在抽象类中定义依赖于参数/返回满足条件的泛型方法Data<E,S>,但也希望能够返回/使用更明确的类型。例如,在 中Data<E,S>,可能有

E doSomething(E toThis) { toThis.aDataClassMethod(); return toThis; }

该类可以进行第一次调用,因为它知道E是 a Data<E,S>,并返回更具体的类型,因为它知道toThis是 a E

老实说,递归泛型通常是过于聪明的道路。它们可能很有用,但很多时候它们只是“整洁”,人们试图将问题转向一些聪明的东西,而不是反过来。

于 2011-01-11T13:34:02.827 回答
0

我同意 Carl 的观点,即递归类型往往以牺牲可用性为代价“聪明”。然而,在很多情况下,Java rtl 应该使用这个习惯用法来强制执行严格的类型安全并避免我们作为类库拥有的猴子桶。

例如,即使Object也应该是抽象递归类型,至少要强制执行严格的相等规则:

public abstract class Object<T extends Object<T>> {
  ...
  public boolean equals( o :T ) {
     ...
  }
}

在您的 equals() 实现中不再进行 instanceof 检查,更重要的是,更好地在编译时检查 equals() 调用。

也就是说,也许更合适且不太复杂的功能将是“自我”类型......

于 2014-06-20T21:40:25.830 回答