vico
vico

Reputation: 18171

Protected access modifier allows access field in not derived case

I have class c1 in package bbb:

package bbb;

public class c1 {

     protected static  int a = 5;

}

I have to classes that imports c1:

    package aaa;
    import bbb.c1;
    public class c2 extends c1 {

        public c2() {
            a = 10;
            c1 c = new c1();
            c.a = 60;
        }
    }


package aaa;
import bbb.c1;
public class c4 {

    public c4() {

        c1 c = new c1();
        c.a = 60;
    }
}

Both c2 and c4 uses c1. c2 derives from c1 while c4 - not. I'm interest in in variable c in both of these classes. In case of class c4 I have compilation error "a has protected access in bbb.c1" while in c2 case c variable works fine.

I was expected that derived class might use internal field a, but should not allow using it in newly created c variable like it did in c4 case since that fact that it is not accessing field via deriving. Where is logic?

UPD

Book Mala Gupta "OCA Java SE 8 Programmer I Certification Guide" has reference that tells that derived class objects can access protected methods only by inheritance and not reference:

Default access can be compared to package-private (accessible only within a package), and protected access can be compared to package- private + kids (“kids” refer to derived classes). Kids can access protected methods only by inheritance and not by reference (accessing members by using the dot operator on an object)

Is that mistake ?

Upvotes: 0

Views: 78

Answers (3)

Guy
Guy

Reputation: 50864

The access to the protected field a is allowed in c2 constructor since c2 is a sub class of c1. From JLS

If the access is by a qualified name Q.Id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S.

Upvotes: 1

Burcea Bogdan Madalin
Burcea Bogdan Madalin

Reputation: 194

I think this is a common misunderstanding that people get. If a class has access to a property of its own (like c1.a, in your case), then it has access to that same property in another instance of the same class, regardless of its access modifier (even private). For instance, this works:

class Base {
    private int x = 0;

    public void method(Base other) {
        other.x += 5;
    }
}

If you are wondering why, I guess this is just how it was designed to be. I imagine other languages that support Object Oriented design work the same (I know it does in C++).

Note: This is not relevant to your question, but it is a good convention to name your classes with uppercase starting words (C1, C2, C4 here), so that code is easier to read by others.

Upvotes: 0

Oleg Cherednik
Oleg Cherednik

Reputation: 18245

public class c4 {

    public c4() {

        c1 c = new c1();
        c.a = 60;
    }
}

Class c1 is public, therefore c4 from another package has access to it. But, variable c1.a is protected, it means that it's visible only to package bbb or any child of c1. So, c.a = 60; is CompileTimeError, because c1.a is not visible from the bbb package and c4 does not extends c1.


The official tutorial may be of some use to you.

______________________________________________________________
|           │ Class │ Package │ Subclass │ Subclass │ World  |
|           │       │         │(same pkg)│(diff pkg)│        |
|───────────┼───────┼─────────┼──────────┼──────────┼────────|
|public     │   +   │    +    │    +     │     +    │   +    | 
|───────────┼───────┼─────────┼──────────┼──────────┼────────|
|protected  │   +   │    +    │    +     │     +    │        | 
|───────────┼───────┼─────────┼──────────┼──────────┼────────|
|no modifier│   +   │    +    │    +     │          │        | 
|───────────┼───────┼─────────┼──────────┼──────────┼────────|
|private    │   +   │         │          │          │        |
|___________|_______|_________|__________|__________|________|
 + : accessible         blank : not accessible

Upvotes: 0

Related Questions