4

I have a class:

package foo;
public abstract class AbstractClause<T>{
    protected T item;
    protected AbstractClause<T> next;
}

and its subclass (in different package):

package bar;
import foo.AbstractClause;

public class ConcreteClause extends AbstractClause<String>{

    public void someMethod(ConcreteClause c) {
        System.out.println(this.next);      // works fine
        System.out.println(c.next);         // also works fine
        System.out.println(this.next.next); // Error: next is not visible
    }
}

Why?

Pshemo
  • 122,468
  • 25
  • 185
  • 269
user3663882
  • 6,957
  • 10
  • 51
  • 92
  • 5
    possible duplicate: http://stackoverflow.com/questions/20534990/protected-variable-from-super-class-not-visible-from-subclass-in-different-packa http://stackoverflow.com/questions/3071720/why-cant-my-subclass-access-a-protected-variable-of-its-superclass-when-its-i – user140547 Jun 19 '15 at 13:13
  • Well it's being accessed from withihn the subclass. What's wrong? – user3663882 Jun 19 '15 at 13:14
  • 2
    Are you getting the error at compile time or runtime? Because I can compile your sample code just fine. – sstan Jun 19 '15 at 13:16
  • 2
    There's nothing wrong with the code above. Please provide exact error message. – NickJ Jun 19 '15 at 13:21
  • @sstan Was your derived class placed in different package than base class? – Pshemo Jun 19 '15 at 13:22
  • @Pshemo: No, they were in the same package. But you are right: as soon as I move the 2 classes to separate packages, I can't compile anymore. I just upvoted user140547's comment. The links posted are very relevant. – sstan Jun 19 '15 at 13:23
  • @Pshemo Obviously, yes. They are in the different packages. – user3663882 Jun 19 '15 at 13:27
  • So, basically, according to the other SO q/a, `this.next` is accessible (as it should), but `this.last.next` is not accessible because `this.last` refers to a completely distinct instance that is not part of this instance's hierarchy tree. – sstan Jun 19 '15 at 13:27
  • @user3663882 That is not very obvious at all. Anyway I updated your question to reflect that. – Pshemo Jun 19 '15 at 13:28
  • @Pshemo Well, if they were in the same packge the compile error wouldn't occur then. – user3663882 Jun 19 '15 at 13:30
  • @user3663882 I am not saying it has no sense, I am saying it is not obvious (at least at first) so it could cause some misunderstandings where people would not be able to reproduce your problem. – Pshemo Jun 19 '15 at 13:37

1 Answers1

3

It seems that if the subclass is in a different package, then methods can only access their own protected instance fields, not those of other instances of the same class. Hence this.last and this.next work because they access the fields of this object, but this.last.next and this.next.last will not work.

public void append(RestrictionClauseItem item) {
    AbstractClause<Concrete> c = this.last.next; //Error: next is not visible
    AbstractClause<Concrete> d = this.next; //next is visible!
    //Some other staff
}

EDIT - I wasn't quite right. Thanks for the upvotes anyway :)

I tried an experiment. I have this class:

public class Vehicle {
    protected int numberOfWheels;
}

And this one in a different package:

public class Car extends Vehicle {

  public void method(Car otherCar, Vehicle otherVehicle) {
    System.out.println(this.numberOfWheels);
    System.out.println(otherCar.numberOfWheels);
    System.out.println(otherVehicle.numberOfWheels); //error here!
  }
}

So, it's not this which is the important thing. I can access protected fields of other objects of the same class, but NOT protected fields of objects of the supertype, since reference of supertype can hold any object, not necessary subtype of Car (like Bike) and Car can't access protected fields inherited by different type from Vehicle (they are accessible only to extending class and its subtypes).

Pshemo
  • 122,468
  • 25
  • 185
  • 269
NickJ
  • 9,380
  • 9
  • 51
  • 74
  • Can you elaborate "can only access their own protected instance fields, not those of other instances of the same class." part? Also I updated OP code to show that derived class has access to its own fields and also fields of other instances of derived type (take a look at `System.out.println(c.next);` part). – Pshemo Jun 19 '15 at 13:47
  • In other words `protected` member is accessed from reference of `Derived` class, but is not accessible from reference of `Parent` class (which makes sense because such reference could hold instance of other type than our Derived class which so we shouldn't have access to it). – Pshemo Jun 19 '15 at 13:51
  • 1
    @Pshemo I was wrong - I have updated my answet – NickJ Jun 19 '15 at 13:59