避免泛型类型的表单Foo< ActualType扩展Foo< ActualType>> [英] Avoiding generic types of form Foo<ActualType extends Foo<ActualType>>

查看:73
本文介绍了避免泛型类型的表单Foo< ActualType扩展Foo< ActualType>>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常发现自己希望编写表单的泛型类定义。

  public class Foo< ; ActualType扩展Foo< ActualType>> 

例如在这样的设置中:

< pre class =lang-java prettyprint-override> public interface ChangeHandler< SourceType> {
public void onChange(SourceType source);
}


public class Foo< ActualType extends Foo< ActualType>> {

private final List< ChangeHandler< ActualType>> handlers = new ArrayList<>();

public void addChangeHandler(ChangeHandler< ActualType> handler){
handlers.add(handler);
}
$ b @SuppressWarnings(unchecked)
protected void reportChange(){
for(ChangeHandler< ActualType>处理程序:处理程序)
处理程序。 onChange((ActualType)this);
}
}


public class Bar扩展Foo< Bar> {
//在这里发生的事情叫super.reportChange();


$ b public static void main(String [] args)throws IOException {

Bar bar = new Bar();
bar.addChangeHandler(new ChangeHandler< Bar>(){

@Override
public void onChange(Bar source){
//对已更改的对象执行某些操作
}
});
}

这里的change-event只是一个例子。当我想让超类为每个特定的子类提供个性化的功能时(不确定如何更好地描述这个更好......在这个例子中),这更多的是我遇到的一个普遍问题在个性化之上的是事实上, ChangeHandler 用实际子类型的对象( Bar )不是与调用处理函数的超类( Foo )类型有关。



不知何故对我来说似乎有点混乱。它实际上允许潜在的问题,因为没有任何东西可以阻止我定义:

  public class Baz extends Foo< Bar> {/ * ... * /} 

是否有更清洁的选择?

圣杯是一些总是定义为包含当前类的类型参数,如的静态版本this.getClass() 可以让我编写这样的代码:

  public class Foo {

private final List< ChangeHandler< this.Class>> handlers = new ArrayList<>();

public void addChangeHandler(ChangeHandler< this.Class> handler){
handlers.add(handler);

$ b保护无效reportChange(){
(ChangeHandler< this.Class>处理程序:处理程序)
handler.onChange(this);


其中 this.Class 将等于 Bar ,用于类型为 Bar 的类。

$ b $我建议我们简单地使用< This> 来表示自我类型。无需限制,因为它看起来很复杂,不能传达意图,也无法强制约束。

  public class FOO<这> {

private final List< ChangeHandler< This>> handlers = new ArrayList<>();

public void addChangeHandler(ChangeHandler< This> handler){
handlers.add(handler);
}
$ b @SuppressWarnings(unchecked)
protected void reportChange(){
for(ChangeHandler< This> handler:handlers)
handler。 onChange((This)this);


$ / code>

注意铸造



另见 Java泛型:使用此类型作为返回类型?


I frequently find myself wanting to write generic class definitions of the form

public class Foo<ActualType extends Foo<ActualType>>

For example in a setup like this:

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


public class Foo<ActualType extends Foo<ActualType>> {

    private final List<ChangeHandler<ActualType>> handlers = new ArrayList<>();

    public void addChangeHandler(ChangeHandler<ActualType> handler) {
        handlers.add(handler);
    }

    @SuppressWarnings("unchecked")
    protected void reportChange() {
        for (ChangeHandler<ActualType> handler: handlers)
            handler.onChange((ActualType) this);
    }
}


public class Bar extends Foo<Bar> {
    // things happen in here that call super.reportChange();
}


public static void main(String[] args) throws IOException {

    Bar bar = new Bar();
    bar.addChangeHandler(new ChangeHandler<Bar>() {

        @Override
        public void onChange(Bar source) {
            // Do something with the changed object
        }
    });
}

The change-event here is just an example. This is more of a general problem that I'm having whenever I would like to allow a super-class to provide functionality that is "individualized" to each specific sub-class (not sure how to phrase this better... in the example above the "individualization" is the fact that the ChangeHandler is called with an object of the actual sub-type (Bar) not with the type of the super-class (Foo) that is calling the handler).

Somehow this approach seems a bit messy to me. And it actually allows for potential issues since nothing prevents me from then defining:

public class Baz extends Foo<Bar> { /* ... */ }

Is there a cleaner alternative?

The holy grail would be some type parameter that is always defined to contain the current class, like a static version of this.getClass() that would allow me to write something like this instead:

public class Foo {

    private final List<ChangeHandler<this.Class>> handlers = new ArrayList<>();

    public void addChangeHandler(ChangeHandler<this.Class> handler) {
        handlers.add(handler);
    }

    protected void reportChange() {
        for (ChangeHandler<this.Class> handler: handlers)
            handler.onChange(this);
    }
}

Where this.Class would be equal to Bar for classes of type Bar.

解决方案

I would recommend that we simply use <This> to represent the "self type". No need for bound, since it looks complicated, doesn't deliver the intention, and cannot enforce the constraint anyway.

public class Foo<This> {

    private final List<ChangeHandler<This>> handlers = new ArrayList<>();

    public void addChangeHandler(ChangeHandler<This> handler) {
        handlers.add(handler);
    }

    @SuppressWarnings("unchecked")
    protected void reportChange() {
        for (ChangeHandler<This> handler: handlers)
            handler.onChange( (This)this );
    }
}

Notice the cast (This)this.

See also Java generics: Use this type as return type?

这篇关于避免泛型类型的表单Foo&lt; ActualType扩展Foo&lt; ActualType&gt;&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆