1

I would like to know how to write a class in Java that has a nested template parameter. This question describes nested, template parameters, but assumes that wildcards will be used. I would like to name all the types involved, so I don't want to use wildcards. Note that I understand that the wildcards are used for covariance. I am perfectly fine with my templated type being invariant as long as I know the types it's made out of. Below is an example of code that compiles, but doesn't give me all the information I want.

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);
    }
}

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;
    }
}


public class Main {
    public static void main(String[] args) {
        Parent<String> stringParent = new Parent<>("hello");
        Child<Integer> intChild = new Child<>(5);

        Foo<Parent, String> foo = new Foo<>(stringParent, "bonjour");
        Foo<Child, Integer> childFoo = new Foo<>(intChild, 42);

        Object b = foo.parent.b;
        System.out.println(b + ", " + b.getClass());
    }
}

I am forced to declare the type of foo.parent.b as an Object, even though I know it is a String (and the program knows it too: the output is hello, class java.lang.String). I would like to write the code more like this:

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;
    }
}

or something along those lines, explicitly forcing parent's type to be linked to 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

The locations where the error occurs are marked above.

1 Answer 1

2

This is because you didn't specify the type parameter of Parent here:

Foo<Parent, String> foo = new Foo<>(stringParent, "bonjour");
Foo<Child, Integer> childFoo = new Foo<>(intChildBar, 42);

Object b = foo.parent.b;

Instead of Foo<Parent, String>, if you specify the type parameter of Parent, that is Foo<Parent<String>, String>, then you can get the correct type of b:

Foo<Parent<String>, String> foo = new Foo<>(stringParent, "bonjour");
Foo<Child, Integer> childFoo = new Foo<>(intChildBar, 42);

String b = foo.parent.b;
Sign up to request clarification or add additional context in comments.

3 Comments

@JonMcClung if you read janos answer, it pretty much tells you the next answer, you know how he mentions to change the Parent to Parent<String>... are things clicking?
@Snickers3192 sorry, things aren't exactly clicking. I've tried just adding <B> to various parts of the class, but that only results in errors. My follow-up question is here if you'd like to provide more insight: stackoverflow.com/q/41217172/4714742
You need to add type parameters to Parent at the start of your Foo declaration. By the way your child class is redundant. You should think really carefully about how to use inheritance in your design of a class hierarchy. Helpful tip: if you don't add any methods to an inherited class, you probably don't need inheritance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.