Code Complete
Code Complete

Reputation: 3206

Package-private member visibility in complex inheritance / package combinations - Qiuck General Rule to verify visibility

If Base and Derived classes are in different packages then package-private member from Base shall not be inherited and thus it shall be absent in Derived, that is such member shall be inaccessible both thru Base obj = new Derived() and Derived obj = new Derived() -obj.member() shall give a compile error in either case!

But I see that for Base obj = new Derived(), obj.f() is accessible!

Yes, private members are still there because when I create new Derived() then new Base() is also created with all its private members (under the hood). But if I change package-private f() in code below to private, obj.f() would be compile error for Base obj = new Derived(), as expected... Anyway, I suspect that in my example with package-private members, it is exactly like this - having access from Derived class to (implicitly existing) private (-) members of its superclass (Base class).

(-) (because Base and Derived are in different packages)

package com.main_pkg;

public class Base {     
    void f() { } // default visibility        
}

and

package org.another_pkg;

import com.main_pkg.Base;

public class Derived extends Base {         

}

and

package com.totally.different_pkg;

import org.another_pkg.Derived;

public class DerivedFromDerived extends Derived {

}

finally

import org.another_pkg.Derived;

import com.totally.different_pkg.DerivedFromDerived;

public class Driver {  // Base class is in same pkg as Driver!

    public static void main(String[] args) {
        Base obj1 = new Derived();
        obj1.f(); // f() is visible!

        Base obj2 = new DerivedFromDerived();
        obj2.f();  // f() is visible!
    }
}

Could you please formulate a quick-and-easy practical rule (in other words than in JLS and common-place default-visibility definitions) how to understand visibility (access) in complex inheritance / package combinations(we might have complex hierarchy Base->Derived->Derived2->Derived3 and every class(es) can be in same/different packages. How to quess accessibility quick?

For example, for a protected member (of Base class) the "quick-guess" rule is very simple:

  1. if Base and Driver are in same package (that is from any Driver's method the code Base obj = new Base(); obj.baseProtectedMember(); compiles) => any combination would work (Base obj1 = new Derived2(); Derived2 obj2 = new Derived2(), etc - obj1.baseProtectedMember() and obj2.baseProtectedMember() are visible and can be called). And we do not care in what packages other classes are!
  2. if Base and Driver are NOT in same package (that is from any Driver's method the code Base obj = new Base(); obj.baseProtectedMember(); DOES NOT compile) => any combination (see 1) would NOT work. And we do not care in what packages other classes are!

But for package-private members we do care about in which package which hierarchy class is, and I cannot formulate an easy and reliable "quick-guess" rule for the general case...

P.S. Interesting SIDE-NOTE:

If I override methods in Derived and DerivedFromDerived (leaving them package-private) in the code-snippet above (at the top of the post), the output is:

f() from Base called
f() from Base called

Upvotes: 0

Views: 65

Answers (1)

Robert Bain
Robert Bain

Reputation: 9576

Base and Driver are in the same package, so Driver can see Base's package private methods. If you declared Base obj1 = new Derived() as Derived obj1 = new Derived() you would not see f(). The same holds true for Base obj2 = new DerivedFromDerived(), in that if you declared it as a DerivedFromDerived, you would not see f().

Upvotes: 1

Related Questions