7
votes

When I was going through this article, under the section Private Members in a Superclass, i saw this line

A nested class has access to all the private members of its enclosing class—both fields and methods. Therefore, a public or protected nested class inherited by a subclass has indirect access to all of the private members of the superclass.

My question is how can we DIRECTLY access the Nested class of Base in Derived (like we can access any public, protected fields)?

and

if there is a way, how can Derived access p which is private field of Base through Nested?

public class Base {

    protected int f;
    private int p;

    public class Nested {

        public int getP() {
            return p;
        }
    }
}

class Derived extends Base {

    public void newMethod() {
        System.out.println(f); // i understand inheriting protected field

        // how to access the inherited Nested class here? and if accessed how to retrieve 'p' ?
    }

}

Thanks in advance for your time and effort in this thread!

3

3 Answers

3
votes
Base.Nested theClassBro= new Base.Nested();

Or for the Derived class, this should work:

Derived.Nested theClassBro= new Derived.Nested();

I'm not sure if you need to use the super keyword or not

2
votes

A non-static inner class always needs an enclosing instance of the class it is nested in. Within code defined in class Base or class Derived (because it inherits the inner class), you can simply write

Nested nested = new Nested();

To create a new instance. You can then invoke the getP() method on the Nested reference to get to the value of the private p value. This value is part of the instance of class Base that encloses the instance of Nested.

Because the inner class is public, code defined outside of Base or Derived can also create an instance. But this requires an enclosing instance of either Derived or Base. Java has special syntax for this where you invoke the new operator on an instance of the enclosing class. So outside of Base or Derived you can do:

Base base = new Base();
Base.Nested baseNested = base.new Nested();    
Derived derived = new Derived();
Derived.Nested derivedNested = derived.new Nested();
Base.Nested d = derivedNested;

It is also possible to import Base.Nested so that you can write:

Base base = new Base();
Nested baseNested = base.new Nested();
Derived derived = new Derived();
Nested derivedNested = derived.new Nested(); // Base.Nested reference

It's good to know this syntax, but I feel code is generally cleaner (easier to understand, better encapsulation) if only the enclosing class is allowed to create new instances of the inner class. You can also use a static nested class if you need a class that logically belongs only to Base but does not need an enclosing instance.

0
votes

As you may know, Nested can only be created when there is an enclosing instance of the class containing the Nested class definition, in our case it's the Enclosing class. To be able to access the private members of the Enclosing class through inheritance of its Nested class, we need to provide to the constructor of the Derived class, the enclosing instance that contains Enclosing.Nested. The following code should make it clearer to understand. I have changed the names of the variables and classes from your original example for better understanding:


public class Enclosing {

    protected int protectedMember = 3;
    private int privateMember = 7;

    public class Nested {

        public int getPrivate() {
            return privateMember;
        }

        public int getProtected() {
            return protectedMember;
        }

    }

}

class Derived extends Enclosing.Nested {

    //Provide the enclosing instance that contains Enclosing.Nested
    public Derived() {
        new Enclosing().super();
    }

    //Access protected member of Enclosing class
    public void accessProtectedMember() {
        System.out.println(getProtected());
    }

    //Access private Member of Enclosing class
    public void accessPrivateMember() {
        System.out.println(getPrivate());
    }

}

public class Test {
    public static void main(String... args) {
        Derived derived = new Derived();
        derived.accessProtectedMember();
        derived.accessPrivateMember();
    }
}