0

I did a little bit of research to know if private instance fields and methods are inherited by a subclass from its superclass.

Actually, I red on different forums contradictory answers but the most convincing one was that, like the java documentation tells, private fields and methods are never inherited BUT that instances of the subclass allocate some memory for the private fields and methods of the superclass.

However, on my most reliable source of documentation, which is the book "java in a nutshell 6th edition" it is said :

This existence of potentially inaccessible members seems to be in conflict with the statement that the members of a class are always accessible within the body of the class. To clear up this confusion, we define “inherited members” to mean those superclass members that are accessible.

Then the correct statement about member accessibility is: “All inherited members and all members defined in this class are accessible.” An alternative way of saying this is:

• A class inherits all instance fields and instance methods (but not constructors) of its superclass.

• The body of a class can always access all the fields and methods it declares itself. It can also access the accessible fields and members it inherits from its superclass.

So according to my understanding I came to the conclusion that a subclass inherits ALL fields and methods (including the private ones) from its superclass, but somehow the body of the subclass cannot access the private (and eventually other invisible) members of the superclass.

If I understood well what the book says, isn't that contradictory with what the java documentation tells - that private members are not even inherited -? Or did I just missed something while reading the book?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
G f a e
  • 1
  • 1
  • 4
    They are. They are not accessible from the subclass, but they are indeed inherited. – BackSlash Mar 02 '18 at 20:15
  • "_like the java documentation tells, private fields and methods are never inherited_" Can you show where you read this? – takendarkk Mar 02 '18 at 20:20
  • Hey csmckelvey It is from the book "Java in a Nutshell", 6th edition, Part 1 Chapter 3. Can't find the pdf link tho – G f a e Mar 02 '18 at 20:24
  • 2
    @csmckelvey ["Members of a class that are declared `private` are not inherited by subclasses of that class."](https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2) – Radiodef Mar 02 '18 at 20:28
  • 1
    The snippet from your 'nutshell' book - and indeed the Java Language Specification - are defining 'inherited' in a different way than some/many/most of us intuitively expect. They are tying it to accessibility. The private member remains in the superclass; because it is not accessible by a subclass, it is *by definition* not inherited. – kem Mar 02 '18 at 20:41

2 Answers2

2

Whether a member is inherited or not is primarily relevant to lookup procedures. If e.g. a class B extends A, when the language specification says that private members are not inherited, what this means is that the private members of A only belong to instances of B while viewing them as an A.

The classic example of this looks something like this:

class B extends A {}

class A {
    private void m() {}
    
    public static void main(String[] args) {
        B b = new B();
        b.m(); // error: "cannot find symbol"
        A a = b;
        a.m(); // fine: m() is a member of A
    }
}

There is indeed a method m() which we can call on the instance of B, but the method lookup procedure fails to find it unless we're viewing the B as an A.

With private fields, the in-memory representation of an object will include the private fields of its superclasses, even though we say they are not inherited in JLS terms.

Some further clarifications here are in §8.2:

Members of a class that are declared private are not inherited by subclasses of that class.

Only members of a class that are declared protected or public are inherited by subclasses declared in a package other than the one in which the class is declared.

As well as in §8.3:

A class inherits from its direct superclass and direct superinterfaces all the non-private fields of the superclass and superinterfaces that are both accessible to code in the class and not hidden by a declaration in the class.

A private field of a superclass might be accessible to a subclass - for example, if both classes are members of the same class. Nevertheless, a private field is never inherited by a subclass.

(§8.4.8 also has similar rules for methods.)

These clarify that inheritance does have something to do with accessibility, but there's not a strict 1:1 correspondence. For example, in the following, the field x is accessible to, but not inherited by class B (per §8.3 above):

class Outer {
    static class A {
        private int x;
    }
    static class B extends A {
        B() {
            super.x = 1; // accessible, but must be qualified
        }
    }
}

One way to put this is that accessibility is a necessary, but not sufficient, condition for inheritance. (In other words, inheritance requires accessibility, but not vice versa.)

Colloquially, it's probably correct to say that private members are inherited, in the sense that 1) a subclass object stores the private variables of its superclasses and 2) the private methods of the superclasses can be invoked on a subclass instance. This is, however, not how the JLS is using the word.

Community
  • 1
  • 1
Radiodef
  • 37,180
  • 14
  • 90
  • 125
1

Consider

class A {
   private int x;
   public A() {
     x = 10;
   }
   public int foo() {
      return x * 2;
   }
}

public class B extends A {
   public B() {
      super();  // Calls A's constructor assigning x.
      // anything
   }
}

int n = B().foo();  // n == 20

It is apparent that an instance of B does carry the member x, with its value. If B did not do so, it could not run the inherited method foo, because that method's implementation in A needs the value of x.

Indeed, B cannot directly access x. But as long as it has any methods that (transitively) depend on that value, via inheritance from A, it must allocate storage for x.

In other words, B is A with something added. Nothing can be removed by inheritance. It can only be made invisible, it it was private. But it's still there, not gone.

9000
  • 39,899
  • 9
  • 66
  • 104
  • Thank you for your answer. It makes sense but is it not contradictory with the oracle documentation that explicitly says : "A subclass does not inherit the private members of its parent class."? – G f a e Mar 02 '18 at 20:29