简体   繁体   中英

Why an instance of inherited class can't access to protected member of base class in different package

I have 3 class A, B, C :

package com.training.protectedclass.A;

public class A
{
    protected int   value;
}

package com.training.protectedclass.B;
import com.training.protectedclass.A.A;

public class B extends A
{
    public void test()
    {
        this.value = 10;
        A a = new A();
        a.value = 12; //Error => The field A.value is not visible
    }
}

package com.training.protectedclass.C;

import com.training.protectedclass.B.B;
import com.training.protectedclass.A.A;

public class C extends A
{
    public void test()
    {           
        B b = new B();
        b.value = 45; //Error => The field A.value is not visible
    }
}

When the inherited class exists in different package than the base class, it can't access the protected member of base class. But when all the three class exist in the same package the above errors disappear and the code is compiled without errors.

Can anyone explain me the cause of each error launched in my code above?

Thanks :)

This is because protected in Java means two things: 1) inherited classes can see protected members that they inherit, and 2) other classes in the same package can see protected members (even if they don't inherit the member).

So in class B you have inherited value and thus you can access it via this.value , but as class A is in another package you can't see a.value . This is because when you call a.value you are accessing a member of a class in another package rather than the inherited version of the field value .

In the case of class C , you can't access any protected member of B because you neither inherit from B nor are in the same package as B .

The Java Language Specification defines the protected access modifier this way:

A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.

When you have this.value = 10; , the B object accesses to one of its own members, which is a protected field declared in the superclass. On the other hand, when you have new A().value , the B object tries to access a protected member of an object that it doesn't implement.

Documentation in http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html says this.

The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.

But your problem is, you are trying to access a protected member of a different object than this . Check this one out http://bmanolov.free.fr/javaprotection.php

I think JLS 6.6.2.1 gives the answer:

Let C be the class in which a protected member is declared. Access is permitted only within the body of a subclass S of C.

In addition, if Id denotes an instance field or instance method, then:

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.

If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S.

You're accessing the member value in the body of B . Therefore, for applying this clause, S is B , and according to the last paragraph, when you try to access E.value for some expression E, the access is permitted only if the type of E is B or a subclass of B. Since the type is A, which isn't a subclass of B, this condition fails.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM