• Post Reply Bookmark Topic Watch Topic
  • New Topic

protected access between instances  RSS feed

 
jon ruane
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
i came across this question. now the answer is that the code in B.java fails to compile as we are trying to access a's integer 'i', through a 'b'object.

now i could try memorise this rule, but if someone could explain why this is so, and why if you change the access modifier of 'a' to public, the code compiles, then i think this rule will stick in my head.


Consider following two classes:
//in file A.java

package p1;
public class A{
protected int i = 10;

public int getI() {
return i;
}
}

//in file B.java

package p2;
import p1.*;

public class B extends p1.A {
public void process(A a) {
a.i = a.i*2;
}

public static void main(String[] args) {
A a = new B();
B b = new B();
b.process(a);
System.out.println(a.getI());
}
}
 
Jesper de Jong
Java Cowboy
Sheriff
Posts: 16028
87
Android IntelliJ IDE Java Scala Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is a bit complicated, I hope I can explain this well...

protected means: visible in other classes in the same package and in subclasses (in the same package or in a different package).

Now in your method process(...) in class B, you are passing an A object. At first sight, it seems like the 'i' in that A object should be visible, because even though class B is not in the same package as class A, class B is a subclass, and protected members should be visible in subclasses.

Well, the argument to the process(...) method is an A object. (I know you're passing it a B object in your main(...) method, but that's at runtime - the method is declared with A, so as far as the compiler is concerned the method works with any kind of A object).

It can be any kind of A object - suppose you had a class C that extends A, and you'd pass a C object to the method. Then you wouldn't expect B.process(...) to have access to the C's protected members - B isn't a subclass of C.

There are a number of different ways to get this to compile:
  • Make i public in class A.
  • Put class A and B in the same package.
  • Make the argument of the method process(...) B instead of A.

  •  
    Jeffrey Bennett
    Greenhorn
    Posts: 12
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I'll assume this is a contrived example as there are a number of bad-habits illustrated.

    Bad encapsulation: A should define 'i' as private and provide get/set methods as appropriate. Scope of get/set might be either public or protected depending...

    Bad object-orientation: Seems strange that the process method on B would impact the A argument. Seems like that method would better belong on A. Similarly, B undergoes no change in this method (it might as well be static on B).
     
    Keith Lynn
    Ranch Hand
    Posts: 2409
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    This is discussed in the Java Language Specification 6.6.7.

    6.6.7 Example: protected Fields, Methods, and Constructors
    Consider this example, where the points package declares:

    package points;
    public class Point {
    protected int x, y;
    void warp(threePoint.Point3d a) {
    if (a.z > 0) // compile-time error: cannot access a.z
    a.delta(this);
    }
    }

    and the threePoint package declares:

    package threePoint;
    import points.Point;
    public class Point3d extends Point {
    protected int z;
    public void delta(Point p) {
    p.x += this.x; // compile-time error: cannot access p.x
    p.y += this.y; // compile-time error: cannot access p.y

    }
    public void delta3d(Point3d q) {
    q.x += this.x;
    q.y += this.y;
    q.z += this.z;
    }
    }

    which defines a class Point3d. A compile-time error occurs in the method delta here: it cannot access the protected members x and y of its parameter p, because while Point3d (the class in which the references to fields x and y occur) is a subclass of Point (the class in which x and y are declared), it is not involved in the implementation of a Point (the type of the parameter p). The method delta3d can access the protected members of its parameter q, because the class Point3d is a subclass of Point and is involved in the implementation of a Point3d.

    The method delta could try to cast (�5.5, �15.16) its parameter to be a Point3d, but this cast would fail, causing an exception, if the class of p at run time were not Point3d.

    A compile-time error also occurs in the method warp: it cannot access the protected member z of its parameter a, because while the class Point (the class in which the reference to field z occurs) is involved in the implementation of a Point3d (the type of the parameter a), it is not a subclass of Point3d (the class in which z is declared).
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!