避免generics类型的表单Foo <ActualType扩展了Foo >

我经常发现自己想要编写表单的generics类定义

public class Foo<ActualType extends Foo> 

例如,在这样的设置中:

 public interface ChangeHandler { public void onChange(SourceType source); } public class Foo<ActualType extends Foo> { private final List<ChangeHandler> handlers = new ArrayList(); public void addChangeHandler(ChangeHandler handler) { handlers.add(handler); } @SuppressWarnings("unchecked") protected void reportChange() { for (ChangeHandler handler: handlers) handler.onChange((ActualType) this); } } public class Bar extends Foo { // things happen in here that call super.reportChange(); } public static void main(String[] args) throws IOException { Bar bar = new Bar(); bar.addChangeHandler(new ChangeHandler() { @Override public void onChange(Bar source) { // Do something with the changed object } }); } 

这里的变化事件只是一个例子。 每当我想让超类提供对每个特定子类“个性化”的function时,这就是我遇到的一个普遍问题(不确定如何更好地表达这个……在示例中) “个性化”之上的事实是,使用实际子类型( Bar )的对象调用ChangeHandler ,而不是调用处理程序的超类( Foo )的类型。

不知怎的,这种方法对我来说似乎有些混乱。 它实际上允许潜在的问题,因为没有什么能阻止我定义:

 public class Baz extends Foo { /* ... */ } 

有更清洁的选择吗?

圣杯将是一个总是被定义为包含当前类的类型参数,就像this.getClass()的静态版本一样,它允许我写这样的东西:

 public class Foo { private final List<ChangeHandler> handlers = new ArrayList(); public void addChangeHandler(ChangeHandler handler) { handlers.add(handler); } protected void reportChange() { for (ChangeHandler handler: handlers) handler.onChange(this); } } 

其中this.Class等于Bar类的Bar

这是一个非常抽象的问题。 在我看来,“如何使这个更清洁”的简短回答是:只在需要的地方使用generics。

 public class List> 

这是什么意思表达(替代)? 一个只允许保持(T扩展)其他列表的列表,这些列表本身就是我们之前知道的Ts(列表),这些列表只允许保持……等等。 有点循环,我不知道你最终会怎么样?

 public interface ChangeHandler { public void onChange(SourceType source); } 

你为什么要在这里使用generics? 如果您想拥有一个可以处理多种资源类型的更改处理程序,那么您可以创建一个所有实际源inheritance的超类,或者创建一个由源实现的接口。 就像那样,您可以准确地指定源所公开的内容。 或者,源可以在通知时创建源对象而不是传递“this”(然后它更像是一条消息)。 例如:

 public interface ChangeHandler { public void onChange(Source source); } public abstract class Source { private List handlers; protected int nr; public Source(int nr) { this.nr = nr; } public abstract Something getSomething(); public String toString() { return "SRC" + nr; } ... private notify(int index) { handlers.get(i).onChange(this); } } public class Foo extends Source { public Foo(int nr) { super(nr); } public String toString() { return super.toString() + "Foo"; } public Something getSomething() { return new Something(); } } 

你永远不需要演员……或者你呢? 我不确定我是否理解这个问题。

我建议我们只使用来表示“自我类型”。 不需要绑定,因为它看起来很复杂,没有提供意图,并且无论如何都不能强制执行约束。

 public class Foo { private final List> handlers = new ArrayList<>(); public void addChangeHandler(ChangeHandler handler) { handlers.add(handler); } @SuppressWarnings("unchecked") protected void reportChange() { for (ChangeHandler handler: handlers) handler.onChange( (This)this ); } } 

注意演员(This)this

另请参阅Javagenerics:使用此类型作为返回类型?