4

I have two classes in two different packages:

package package1;

public class ParentClass {
    public void testPublic() {
    }

    protected void testProtected() {
    }
}


package package2;

import package1.ParentClass;

public class ChildClass extends ParentClass {
   void test() {
        ParentClass par = new ParentClass();
        par.testProtected(); // Line 1 : ERROR: testProtected() has protected access in ParentClass
        testProtected();     // Line 2 : No error

        ChildClass ch = new ChildClass();
        ch.testProtected(); // Line 3 : No ERROR
        testProtected();    // Line 4 : No error
    }    
}

I am able to understand why there is NO ERROR in calling testProtected() -- Line 2 since ChildClass sees this method as it inherits from ParentClass.

And somehow able to understand why it is throwing ERROR in calling par.testProtected() -- Line 1, since par is a different object, and current object is not having access to other object's parent's protected method.

But how it is possible for an object of ChildClass to access this same method ch.testProtected() -- Line 3 (other object's parent's protected method) when the reference type is of ChildClass only?

lealceldeiro
  • 14,342
  • 6
  • 49
  • 80

1 Answers1

7

The error you're seeing makes total sense.

When you do the following

ParentClass par = new ParentClass();
par.testProtected();

you're trying to access testProtected as if it were part of the public API of ParentClass, that's it, you're calling from another package a protected method of ParentClass on an instance of that class. It doesn't matter it is being called inside an extending class, all that matters is that it's being called from another package.

Now, if you do

ChildClass ch = new ChildClass();
ch.testProtected(); // Line 3
testProtected();    // Line 4

you will not see any errors. Why?

In line 3 you're accessing a method upon an instance of class ChildClass inside ChildClass, so that's legal. Even if you would have had a private method childMethod in ChildClass you could have done ch.childMethod().

In line 4 you're accessing testProtected through the this reference (implicitly), it means it calls the method through the ChildClass, which, again is legal.

See this related post: What is the difference between public, protected, package-private and private in Java? (hint: last row in the described table)

Community
  • 1
  • 1
lealceldeiro
  • 14,342
  • 6
  • 49
  • 80
  • 1
    Understood. In total Protected is a bit complicated than it appears by definition. Definition oversimplifies it. And it is not in par with other access modifiers. Rather than stating a general statement that 'protected members can be accessed by extending ChildClass in diffferent packages', it should say, 'only own (this object's) parent protected members can be accessed within extending ChildClass members in different package'. – Debashish BHARALI Apr 26 '20 at 18:36
  • @DebashishBHARALI This same problem can also occur with private methods. If you have a type `Foo` with a private method `bar()`, and you end up with `var f = someFooType()` where the type of `f` is inferred as `? extends Foo`, then invoking `f.bar()` is a compilation error even when you're inside the class `Foo`. – Slaw Apr 27 '20 at 01:37