Reputation: 3206
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:
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!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
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