How to reference the nested type of a nested template parameter inside a class?

你说的曾经没有我的故事 提交于 2020-01-04 13:46:32

问题


This is a followup to this question. Essentially, I have the following classes:

public class Parent<B> {

    public B b;

    public Parent(B b) {
        this.b = b;
    }
}

public class Child<B> extends Parent<B> {

    public Child(B b) {
        super(b);
    }
}

And I'd like to have another class that references them:

public class Foo<ParentType<B> extends Parent<B>, B> {
//                         ^ syntax error here: > expected
    public ParentType<B> parent;
    public B otherItem;

    public Foo(ParentType<B> parent, B otherItem) {
        this.parent = parent;
        this.otherItem = otherItem;
        B b = parent.b;
    }
}

I think it's clear to a human what I think the above should do, but Java basically considers it a syntactic mess, starting with the first nested <.

I try removing the <B> part in the class template declaration:

public class Foo<ParentType extends Parent, B> {
    public ParentType<B> parent;
//         ^ (5:12)
    public B otherItem;

    public Foo(ParentType<B> parent, B otherItem) {
//                     ^ same error here
        this.parent = parent;
        this.otherItem = otherItem;
        B b = parent.b;
    }
}

but IntelliJ complains

Type 'ParentType' does not have type parameters

and the compiler gives the error:

Error:(5, 12) java: unexpected type
  required: class
  found:    type parameter ParentType

Eventually I can get all the errors to go away if I make the code look like this:

public class Foo<ParentType extends Parent, B> {
    public ParentType parent;
    public B otherItem;

    public Foo(ParentType parent, B otherItem) {
        this.parent = parent;
        this.otherItem = otherItem;
        Object b = parent.b;
    }
}

However, this doesn't allow me to ensure that b is a B, and I want that to be enforced so that I can pass it to a method that accepts a B, for instance.

The answer to my previous question was to add more templating, but I have only been able to get the code to compile by removing some. Is there a trick I'm missing?

I'm aware that I can workaround this problem by casting, but I'd like to have a solution enforced by the compiler if at all possible.


回答1:


Add the type parameter only to the parameterized class, then you should achieve what you want to have:

public class Foo<ParentType extends Parent<B>, B> {
    public ParentType parent;
    public B otherItem;

    public Foo(final ParentType parent, final B otherItem) {
        this.parent = parent;
        this.otherItem = otherItem;
        final B b = parent.b;
    }
}

Now ParentType has to be a subtype of Parent<B> and thus b is a B as long as your ParentType does not override it.



来源:https://stackoverflow.com/questions/41217172/how-to-reference-the-nested-type-of-a-nested-template-parameter-inside-a-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!