Java 递归通用模板:... S extends Writer> 是什么意思?扩展实体
有人可以解释下面相当复杂的递归通用模板用法吗?
public abstract class Data<E extends Data<E, S>,
S extends Writer<E>> extends Entity<E,S>
像上面一样,在使用递归泛型时我们应该记住什么。以及这些类型之间的关系和规则如何,这里是E & S?
如果有的话,请提供一些有关此类通用用法的资源/链接/书籍。 我知道一本讨论这个问题的书,Effective Java,第二版,作者:Joshua Bloch(第 27 项)
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?
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
让我们从最简单的开始
任何类型 S 的类都必须是类 E 的编写者
这里只是继承,Data 类扩展了 Entity 类。
用于 E 的任何类本身都必须从 Data 类继承,并使用其自己的类型和与其自身兼容的编写器继承/实现 Data 的通用方法。
E与E之间的关系S 应该类似于以下内容:
要记住:使用提供
Writer
或Writer
的泛型可能会或可能不会创建编译器错误,这取决于两个泛型类型中定义的泛型方法。Lets begin with the easiest
Any class of type S must be a writer for the class E
Just inheritance here, The Data class extends the Entity class.
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.
The relation between E & S should be something like the following:
To keep in mind: with generics providing a
Writer<SomeChildOfExample>
or aWriter<SomeParentOfExample>
might or might not create compiler errors, this depends on the generic methods defined in both generic types.Data
有两个参数,E
最终必须是其自身的实例,S
必须能够Writer
> 自身的实例(更具体地说,由E
指定的同一类型的自身实例)。最后,Data
还限定为/继承由相同E
和S
参数化的Entity
的功能> (即Entity
属于Data
和Writer
)。具体实现可能类似于
NumericalData extends Data
,其中NumWriter
实现/扩展Writer
和NumericalData
也符合Entity
的资格。编辑:
为什么要做这样的事情?人们可能希望在抽象类中定义通用方法,这些方法依赖于满足条件
Data
的参数/返回,但也希望能够返回/使用更显式的类型。例如,在Data
中,可能有该类可以进行第一个调用,因为它知道
E
是一个Data;
,并返回更具体的类型,因为它知道toThis
是E
。老实说,递归泛型通常是通往聪明之路。它们可能很有用,但很多时候它们只是“简洁”,人们试图通过一些巧妙的方法来解决问题,而不是反之亦然。
Data
has two parameters,E
which must ultimately be an instance of itself, andS
which must be able toWriter
an instance of itself (more specifically, the same kind of instance of itself specified byE
). Finally,Data<E,S>
also qualifies as/inherits capabilities fromEntity
parametrized by the sameE
andS
(i.e.,Entity
is ofData<E,S>
andWriter<E>
).A concrete implementation might look something like
NumericalData extends Data<NumericalData, NumWriter>
whereNumWriter
implements/extendsWriter<NumericalData>
andNumericalData
also qualifies as anEntity<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. For example, inData<E,S>
, there might beThe class can make the first call, because it knows
E
is aData<E,S>
, and return the more specific type because it knowstoThis
is anE
.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.
我同意 Carl 的观点,即递归类型往往会“聪明”,但会牺牲可用性。然而,在很多情况下,Java rtl 应该使用这种习惯来强制执行严格的类型安全,并避免我们作为类库遇到的麻烦。
例如,即使是 Object 也应该是一个抽象递归类型,至少可以强制执行严格的相等规则:
在 equals() 实现中不再进行 instanceof 检查,更重要的是,可以更好地进行 equals 编译时检查() 调用。
也就是说,也许更合适且不太复杂的功能是“自我”类型......
I agree with Carl that recursive types tend to be "clever" at the expense of usability. 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.
For example, even Object should probably be an abstract recursive type at least to enforce strict rules for equality:
No more instanceof checks in your equals() implementations and, more importantly, better compile-time checking for equals() calls.
That said, perhaps a more suitable and less complicated feature would be a "Self" type...