20

I have two classes in two different packages:

package package1;

public class Class1 {
    public void tryMePublic() {
    }

    protected void tryMeProtected() {
    }
}


package package2;

import package1.Class1;

public class Class2 extends Class1 {
    doNow() {
        Class1 c = new Class1();
        c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1
        tryMeProtected();  // No error
    }    
}

I can understand why there is no error in calling tryMeProtected() since Class2 sees this method as it inherits from Class1.

But why isn't it possible for an object of Class2 to access this method on an object of Class1 using c.tryMeProtected(); ?

iggymoran
  • 4,059
  • 2
  • 21
  • 26
user2986848
  • 217
  • 1
  • 2
  • 3
  • 1
    This code does not produce this error. The method tryMeProtected() doesn't exist at all. – user207421 Nov 13 '13 at 09:00
  • 1
    Did you test this with the exact code you posted? if yes it can not work as EJP saied, you have two different names: tryMePublic and tryMeProtected – CloudyMarble Nov 13 '13 at 09:06

8 Answers8

17

Protected methods can only be accessible through inheritance in subclasses outside the package. And hence the second approach tryMeProtected(); works.

The code below wont compile because we are not calling the inherited version of protected method.

 Class1 c = new Class1();
 c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1

Follow this stackoverflow link for more explaination.

Community
  • 1
  • 1
Ankur Shanbhag
  • 7,746
  • 2
  • 28
  • 38
  • outside or in the same package (both of course), not only outside – Mik378 Nov 13 '13 at 08:57
  • 2
    In the same package they are accessible through separate instance as it has same visibility as default in java (except for subclasses which can inherit even outside the package). – Ankur Shanbhag Nov 13 '13 at 08:59
  • Yes, agreed, I would prefer a sentence like: "Inheritance of `protected` methods makes sense only with different packages." ;) – Mik378 Nov 13 '13 at 09:01
  • @Mik378 : Yes correct. I have modified the statement in the post. Thank you for pointing it out. :-) – Ankur Shanbhag Nov 13 '13 at 09:04
14

I believe you misunderstand the difference between package and protected visibility.

package package1;

public class MyClass1 {
    public void tryMePublic() { System.out.println("I'm public"); }
    protected void tryMeProtected() { System.out.println("I'm protected"); }
    void tryMePackage() { System.out.println("I'm package"); }
}
  • tryMePublic will be accessible wherever you are.
  • tryMeProtected will be accessible to every subclass AND every class in the same package.
  • tryMePackage will be accessible to every class in the same package (not available in children class if they are in a different package)

Children class in the same package

package package1;

public class Class2 extends MyClass1 {
    public void doNow() {
        tryMePublic(); // OK
        tryMeProtected(); // OK
        tryMePackage(); // OK
    }    
}

Children class in different package

package package2;

import package1.MyClass1;

public class Class3 extends MyClass1 {
    public void doNow() {
        MyClass1 c = new MyClass1();
        c.tryMeProtected() // ERROR, because only public methods are allowed to be called on class instance, whereever you are
        tryMePublic(); // OK
        tryMeProtected(); // OK
        tryMePackage(); // ERROR
    }    
}
Anthony Raymond
  • 7,434
  • 6
  • 42
  • 59
4

You use two different packages and you don't access your parent attributes by direct inheritance, but by an intermediate parent instance declared in the child class (similar to composition). => that's the not the way protected works.

Only direct inheritance allows protected parent's attributes to be reach.

Thus, you can do this:

public class Class2 extends Class1 {
    doNow() {
        tryMeProtected();  // No error since direct inheritance 
    }    
}

but never this:

public class Class2 extends Class1 {
    doNow() {
        Class1 c = new Class1();
        c.tryMeProtected(); // this is not a direct inheritance! since `c`, although a parent one is an intermediate instance created in the child instance. => bad
    }    
}

Indeed, this is a particularity of protectedkeyword often misunderstood.

Mik378
  • 21,881
  • 15
  • 82
  • 180
  • @CloudyMarble Of course, but the essence of inheritance concept with protected keyword is about different packages. Otherwise, default packages scope would be enough. Of course: who can do more can do less – Mik378 Nov 13 '13 at 09:06
  • 1
    This is the best answer which explains the confusion OP was pointing at. – Mára Toner Oct 13 '22 at 16:20
2

First of all, you need to understand two things:

1) The protected member functions of a class 'X' in package 'Y' can be accessed by the subclass i.e. a class that extends it (even if the subclass is in the package other than 'Y'). That is why,

tryMeProtected(); // Showed no error because this was called by class 2 that is the subclass.

2) A protected member function of a class 'X' in package 'Y' cannot be accessed by itself if it is in other packages.

[ A simple analogy: A bird that has its eggs kept in a nest 1 has flown to a nest 2. From the nest 2, it cannot access its egg kept in nest 1.] Similarly, a class cannot access its member function (unless public declared.) if it is in the other package.

That is why :

c.tryMeProtected();  // Showed error because this was called by class 1 reference.
                     //  You can also think of it as class 1 cannot inherit itself.
Prashant Pimpale
  • 10,349
  • 9
  • 44
  • 84
1

As per Java Protected Access modifier definition methods which are declared protected in a superclass can be accessed only by the subclasses in other package or any class within the package of the protected members' class.

you can't access protected method by creating object of class. So for accessing Protected method you have to extend the superclass.(this explains your 2nd call is correct)

Tushar D
  • 68
  • 1
  • 5
0

It can be acheived by two ways

1. Either by making an object of Child class and then accessing the protected method of Parent class.

PACKAGE 1

public class Class1 {
    protected void m1() {
        System.out.println("m1 called");
    }
}

PACKAGE2

public class Class2 extends Class1 {

    public static void main(String[] args) {
        Class2 class2 = new Class2();
        class2.m1();
    }
}

2. Or by directly calling the method from the Child class

eg tryMeProtected();

beresfordt
  • 5,088
  • 10
  • 35
  • 43
Satyam
  • 74
  • 6
0

the protected modifier is 1.Package Private 2.can be seen by subclasses from other packages. now the key difference between :

MyClass1 c = new MyClass1();
    c.tryMeProtected();

and

tryMyProtected(); 

is that the MyClass1 reference is used rather than inheritance. MyClass1 is in a different package and this code is not inheriting from MyClass1.

0

You Try like this :-

public class Class2 extends Class1 {
    doNow() {
        
Class2 c = new Class2();
       
c.tryMeProtected(); // No error

tryMeProtected();  //  error
    }    

}

tech kid
  • 1
  • 2
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/33688806) – Michael Katt Jan 26 '23 at 12:04