简体   繁体   English

Java递归通用模板:这是什么意思……S扩展了Writer <E> &gt;扩展实体 <E,S>

[英]Java Recursive generic template: what does this mean by … S extends Writer<E>> extends Entity<E,S>

Can some one explain the below, rather complex recursive generic template usage? 有人可以解释以下相当复杂的递归通用模板用法吗?

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

What should we keep in mind while using recursive generics, like above. 如上所述,在使用递归泛型时我们应该记住什么。 And how will be the relation and rules between these types, here E & S ? 这些类型(这里是ES)之间的关系和规则如何?

If any, please provide some resource/links/books about this type of generic usage. 如果有的话,请提供一些有关这种通用用法的资源/链接/书籍。 I know one book talking about this, Effective Java, 2nd ed by Joshua Bloch (Item 27) 我知道一本关于这方面的书,《有效的Java》,约书亚·布洛赫(Joshua Bloch)第二版(第27项)

Lets begin with the easiest 让我们从最简单的开始

S extends Writer<E>

Any class of type S must be a writer for the class E 任何类型为S的类都必须是类E的编写者

extends Entity<E,S>

Just inheritance here, The Data class extends the Entity class. 只是继承,Data类扩展了Entity类。

E extends Data<E, S>

Any class used for E must itself inherit from the Data class and inherits/implements the generic methods of Data using its own type and a writer compatible with itself. 用于E的任何类都必须本身从Data类继承,并使用其自身的类型和与其自身兼容的writer继承/实现Data的通用方法。

The relation between E & S should be something like the following: E&S之间的关系应如下所示:

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

To keep in mind: with generics providing a Writer<SomeChildOfExample> or a Writer<SomeParentOfExample> might or might not create compiler errors, this depends on the generic methods defined in both generic types. 请记住:使用泛型提供Writer<SomeChildOfExample>Writer<SomeParentOfExample>可能会或可能不会产生编译器错误,这取决于这两种泛型类型中定义的泛型方法。

Data has two parameters, E which must ultimately be an instance of itself, and S which must be able to Writer an instance of itself (more specifically, the same kind of instance of itself specified by E ). Data具有两个参数, E必须最终成为其自身的实例,而S必须具有Writer自身的实例的能力(更具体地说,是E指定的自身的同类实例)。 Finally, Data<E,S> also qualifies as/inherits capabilities from Entity parametrized by the same E and S (ie, Entity is of Data<E,S> and Writer<E> ). 最后, Data<E,S>还具有相同的ES参数化的Entity (即, Entity属于Data<E,S>Writer<E> )的资格/继承能力。

A concrete implementation might look something like 具体的实现可能看起来像

NumericalData extends Data<NumericalData, NumWriter> where NumWriter implements/extends Writer<NumericalData> and NumericalData also qualifies as an Entity<NumericalData, NumWriter> . NumericalData extends Data<NumericalData, NumWriter>其中NumWriter工具/延伸Writer<NumericalData>NumericalData也有资格作为一个Entity<NumericalData, NumWriter>

EDIT: 编辑:

Why do something like this? 为什么要这样? One might want to define generic methods in the abstract class that rely on an argument/return meeting the criteria Data<E,S> , but also want to be able to return/work with the more explicit type. 可能需要在抽象类中定义通用方法,该方法依赖于满足条件Data<E,S>的参数/返回值,但也希望能够使用更显式的类型返回/工作。 For example, in Data<E,S> , there might be 例如,在Data<E,S> ,可能存在

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

The class can make the first call, because it knows E is a Data<E,S> , and return the more specific type because it knows toThis is an E . 该类可以进行第一个调用,因为它知道EData<E,S> ,并返回更具体的类型,因为它知道toThisE

To be honest, recursive generics are typically the road to too clever. 坦白地说,递归泛型通常是通往太聪明的道路。 They can be useful, but many times they're just "neat" and one tries to bend the problem around something clever rather than vice versa. 它们可能很有用,但是很多时候它们只是“精巧”的,人们试图将问题转向聪明的事物,而不是相反。

I agree with Carl that recursive types tend to be "clever" at the expense of usability. 我同意Carl的观点,递归类型倾向于“聪明”,但会牺牲可用性。 However there are a LOT of cases where the Java rtl should have employed this idiom to enforce strict type safety and to avoid the barrel of monkeys we have as a class library. 但是,在很多情况下,Java rtl应该采用这种惯用法来强制严格的类型安全性并避免我们作为类库拥有的一堆猴子。

For example, even Object should probably be an abstract recursive type at least to enforce strict rules for equality: 例如,即使Object至少也应该是抽象递归类型,以强制执行严格的相等性规则:

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

No more instanceof checks in your equals() implementations and, more importantly, better compile-time checking for equals() calls. equals()实现中没有更多的instanceof检查,更重要的是,equals()调用的编译时检查更好。

That said, perhaps a more suitable and less complicated feature would be a "Self" type... 也就是说,也许更合适,更简单的功能应该是“ Self”类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM