views:

287

answers:

3

I have an abstract class, relation in package database.relation and a subclass of it, Join, in package database.operations. relation has a protected member named mStructure.

In Join:

public Join(final Relation relLeft, final Relation relRight) {
        super();
        mRelLeft = relLeft;
        mRelRight = relRight;
        mStructure = new LinkedList<Header>();
        this.copyStructure(mRelLeft.mStructure);

        for (final Header header :mRelRight.mStructure) {
        if (!mStructure.contains(header)) {
            mStructure.add(header);
        }
    }
}

On lines

this.copyStructure(mRelLeft.mStructure);

and

for (final Header header : mRelRight.mStructure) {

I get the following error:

The field Relation.mStructure is not visible

If I put both classes in the same package, this works perfectly. Can anyone explain this issue?

+1  A: 

If protected, your instance of Join cannot access the mStructure in other instances (relRight, relLeft) outside the package.

EDIT:

The table here explains this situation fairly well. I marked the culprit in your question with []s

Access Levels
Modifier    Class Package Subclass  World
public      Y     Y       Y         Y
protected   Y    [Y]      Y         N
no modifier Y     Y       N         N
private     Y     N       N         N
Lauri Lehtinen
Mmmhh your first explanation only says, the the OP ask, in fist place , *"can't access it"*. Your edit, doesn't quite clarify the problem.
OscarRyz
I think my 1st explanation says pretty much the same thing as yours.
Lauri Lehtinen
And regarding the edit, how does the table not clarify the problem? The OP described the very behavior that one would expect based on the table - an instance of a class can access the protected members of another instance of any class, if they reside in the same package. Furthermore, an instance of a class can access the protected members defined in its parent class, even if the parent class is in another package.
Lauri Lehtinen
The text accompanying the table you quote specifically says what the OP is doing is allowed - "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. "
Peter Recore
Maybe I'm blissfully reading it wrong then. I guess it comes down to what's considered a "Subclass" in this context.
Lauri Lehtinen
+3  A: 

A little known caveat about protected:

6.6.2 Details on protected Access

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.

Marcus Adams
I find the example under §6.6.7 useful here.
Artefacto
And the formal definition clarifying "responsible for the implementation" is in §6.6.2.1
meriton
+4  A: 

It works, but only you the children tries to access it own variable, not variable of other instance ( even if it belongs to the same inheritance tree ).

See this sample code to understand it better:

//in Parent.java
package parentpackage;
public class Parent {
    protected String parentVariable = "whatever";// define protected variable
}

// in Children.java
package childenpackage;
import parentpackage.Parent;

class Children extends Parent {
    Children(Parent withParent ){
        System.out.println( this.parentVariable );// works well.
        //System.out.print(withParent.parentVariable);// doesn't work
    } 
}

If we try to compile using the withParent.parentVariable we've got:

Children.java:8: parentVariable has protected access in parentpackage.Parent
    System.out.print(withParent.parentVariable);

It is accessible, but only to its own variable.

OscarRyz
Will an appropriate solution be to define a protected accessor?
Amir Rachum
Same thing would happen. More interesting would be to know if `Join` IS-A `Relation` and if so, why should they go in different packages. Probably, using an intermediate object to abstract the structure and would do. I would suggest you to move them in the same package for now, just to avoid enter in a coding paralysis.
OscarRyz