Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parameterizing superclass with static member class from subclass

Tags:

java

generics

Is there a way to parameterize a superclass with a static member class of the subclass?

Contrived Example

ExampleSuperClass.java:

package foo;

public class ExampleSuperClass<T> {
    protected T field;
    
    public ExampleSuperClass(T field) {
        this.field = field;
    }

    public T getField() {
        return field;
    }
}

ExampleSubClass.java:

package foo;

public class ExampleSubClass extends ExampleSuperClass<Member> {

    static class Member {
    
    }
    
    public ExampleSubClass() {
        super(new Member());
    }
}

Compilation fails on ExampleSubClass.java with error:

[javac] ExampleSubClass.java:3: error: cannot find symbol
[javac] public class ExampleSubClass extends ExampleSuperClass<Member> {
[javac]                                                        ^
[javac]   symbol: class Member
[javac] 1 error

or in Eclipse with:

Member cannot be resolved to a type

in Eclipse the super invocation also has the error:

The constructor ExampleSuperClass(Member) refers to missing type Member


It works fine (aka no errors) if ExampleSubClass is instead parameterized with another package-protected top-level class.


Summary

The driving force behind this is that I have a generic super class and many different ${SubClass-extends-GenericSuperClass}.java and ${ClassUsedBySubClass}.java pairs. But since ClassUsedBySubClass is only ever referenced by SubClass, it would be nice to:

  1. restrict ClassUsedBySubClass's access by making it a static member class and
  2. cut down on the number of files by not giving ClassUsedBySubClass its own file.

So, is there a way to use a subclass's member class in parameterizing the superclass?

If there isn't -- is there an alternative approach?

like image 228
xgord Avatar asked May 18 '18 19:05

xgord


3 Answers

Yes, you can do it. However, since Java uses the scope outside the declaration for name resolution, you must qualify Member with the name of ExampleSubClass:

public class ExampleSubClass extends ExampleSuperClass<ExampleSubClass.Member> {
    ...
}
like image 158
Sergey Kalinichenko Avatar answered Nov 11 '22 07:11

Sergey Kalinichenko


Because Member is an inner class, you need to specify that when using it as a generic type. I'm able to get it to compile by using the following:

static class ExampleSubClass extends  ExampleSuperClass<ExampleSubClass.Member> {
    static class Member {

    }

    public ExampleSubClass() {
        super(new Member());
    }
}
like image 8
Jacob G. Avatar answered Nov 11 '22 08:11

Jacob G.


Member is a static nested class. Static nested class is accessed using the enclosing class name:

ExampleSubClass.Member

You do this every time a static nested class occurs outside the scope of its outer class.

Therefore, the following is correct:

public class ExampleSubClass extends ExampleSuperClass<ExampleSubClass.Member> {
                                                              ^
                                                     enclosing class name
    static class Member {
        ...
    }
}

Same as when you want to create an object for the static nested class:

ExampleSubClass.Member member = new ExampleSubClass.Member();
like image 3
Oleksandr Pyrohov Avatar answered Nov 11 '22 07:11

Oleksandr Pyrohov