Java Forum / General / March 2007
Protected inner classes and inheritance
Scott Harper - 29 Mar 2007 21:52 GMT Apologies if I am missing something obvious, but here's the situation. I have a top-level class with a protected inner class. I have a second-level class in a different package that extends the top-level class. For example:
package somePackage;
public class TopLevel { protected class Inner { protected int intField = 0;
protected Inner() { // constructor }
protected void innerMethod() { return; } } }
package somePackage.otherPackage;
import somePackage.TopLevel; import somePackage.TopLevel.Inner;
public class SecondLevel extends TopLevel { public SecondLevel() { // constructor }
public void someMethod() { Inner inner = new Inner();
inner.intField = 1;
inner.innerMethod(); } }
When I compile the second class, I get at least 4 errors:
The type somePackage.TopLevel.Inner is not visible The constructor TopLevel.Inner() is not visible The field TopLevel.Inner.intField is not visible The method innerMethod() from the type TopLevel.Inner is not visible
I thought I read the Java docuementation clearly when is says
"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."
and
"You can use the same modifiers for inner classes that you use for other members of the outer class. For example, you can use the access specifiers -- private, public, and protected -- to restrict access to inner classes, just as you do to other class members."
If I simply make TopLevel.Inner a public class, the errors go away. But I don't really want to do that... Anything obvious??
thanks scott
Scott Harper - 29 Mar 2007 21:58 GMT >If I simply make TopLevel.Inner a public class, the errors go away. But I >don't really want to do that... Check that... I have to make *everything* in the Inner class public to resolve all the errors. And by doing that I no longer need to import the Inner class either...
scott
Scott Harper - 29 Mar 2007 22:00 GMT >>If I simply make TopLevel.Inner a public class, the errors go away. But I >>don't really want to do that... > >Check that... I have to make *everything* in the Inner class public to >resolve all the errors. And by doing that I no longer need to import the >Inner class either... Also, if I move the SecondLevel class into the package somePackage, I can keep the Inner class and its members protected.
Daniel Pitts - 29 Mar 2007 23:28 GMT On Mar 29, 2:00 pm, sharp...@austin.dot.rr.dot.com (Scott Harper) wrote:
> In article <OLVOh.4024$dd.3...@newsread1.mlpsca01.us.to.verio.net>, sharp...@austin.dot.rr.dot.com (Scott Harper) wrote: > [quoted text clipped - 9 lines] > Also, if I move the SecondLevel class into the package somePackage, I can keep > the Inner class and its members protected. Actually, I think the problem is with your import statements: Change them to: import somePackage.TopLevel; //import somePackage.TopLevel.Inner; Or delete this...
and try again.
Piotr Kobzda - 30 Mar 2007 00:49 GMT [...]
> Actually, I think the problem is with your import statements: > Change them to: > import somePackage.TopLevel; > //import somePackage.TopLevel.Inner; Or delete this... It makes an Inner class accessible from SecondLevel. However, it's strange a bit that the compiler checks an access to classes on import statement level... it shouldn't (IMO) !
Anyway, previously inaccessible members of TopLevel.Inner class now might be accessed that way:
public class SecondLevel extends TopLevel { protected /* or private */ class Inner extends TopLevel.Inner { // all protected members of TopLevel.Inner are accessible here...
piotr
Scott Harper - 30 Mar 2007 01:07 GMT >Actually, I think the problem is with your import statements: >Change them to: >import somePackage.TopLevel; >//import somePackage.TopLevel.Inner; Or delete this... > >and try again. no, that doesn't solve it...
scott
Daniel Pitts - 30 Mar 2007 01:18 GMT On Mar 29, 5:07 pm, sharp...@austin.dot.rr.dot.com (Scott Harper) wrote:
> In article <1175207331.047228.108...@n76g2000hsh.googlegroups.com>, "Daniel Pitts" <googlegrou...@coloraura.com> wrote: > [quoted text clipped - 8 lines] > > scott Hmm.. You're right. However, if you make everything public, you can keep Inner protected.
This make sense to me in a way.
Inner's members are protected from anyone who doesn't inherit from Inner. The only inconsistency here is that outer classes can reference inner classes members, regardless of access modifier. Inner itself isn't inherited into SecondLevel, only the namespace of the definition is.
Scott Harper - 30 Mar 2007 02:10 GMT >Hmm.. >You're right. However, if you make everything public, you can keep [quoted text clipped - 7 lines] >isn't inherited into SecondLevel, only the namespace of the definition >is. Ah ha, I hadn't tried that particular permutation, but right you are...
So, I'm not inheriting from Inner, I'm inheriting from TopLevel, which has Inner as a (protected) member. I guess by making Inner itself protected, only my inherited class (SecondLevel) has access to it (outside of Inner's package). And then, because Inner's members are all public, once I can "see" the class, I have access to the public members.
Any other class that didn't inherit from TopLevel wouldn't be able to reference Inner anyway, so it doesn't matter if its members are public or not.
Or is that what you just said? :-)
Just for grins, I made Inner private, and sure enough, even though its members are still public, the inheriting class (SecondLevel) can't resolve them.
thanks scott
Lew - 30 Mar 2007 03:02 GMT > Any other class that didn't inherit from TopLevel wouldn't be able to > reference Inner anyway, so it doesn't matter if its members are public or not. Classes in the same package with TopLevel would see TopLevel's protected members whether or not they extend TopLevel.
-- Lew
Piotr Kobzda - 30 Mar 2007 09:15 GMT [...]
> Any other class that didn't inherit from TopLevel wouldn't be able to > reference Inner anyway, so it doesn't matter if its members are public or not. It's safe, if you do not expose any Inner's instance to the other classes, and Inner constructors are protected (or private). Otherwise, public members are accessible.
For example, the following will change 'intField' of a given TopLevel.Inner instance:
Object innerInstance = ... innerInstance.getClass().getField("intField") .setInt(innerInstance, 100);
> Just for grins, I made Inner private, and sure enough, even though its members > are still public, the inheriting class (SecondLevel) can't resolve them. Even when class is private, reflective access to its public members is still allowed -- standard Java security mechanisms (SecuritManager enabled, etc.) do not prohibit that.
Of course, my first statement from this post still holds here, if you protect an instance and its class' constructors, you are safe.
piotr
Piotr Kobzda - 30 Mar 2007 10:25 GMT > However, if you make everything public, you can keep > Inner protected. [...]
> Inner's members are protected from anyone who doesn't inherit from > Inner. Not fully protected (see my previous post).
> The only inconsistency here is that outer classes can reference > inner classes members, regardless of access modifier. Inner itself > isn't inherited into SecondLevel, only the namespace of the definition > is. Hmm... I don't get it -- there is no any inconsistency IMHO.
AIUI, the Inner class is a member of TopLevel class, and as a member (not a ?namespace?) is inherited by/into the SecondLevel class.
The access modifiers of Inner's members are honored the same way as for any other language element, regardless of the SecondLevel class access level to the Inner class.
That's how I see that. Am I missing something?
piotr
Lew - 30 Mar 2007 14:15 GMT >> However, if you make everything public, you can keep >> Inner protected. [quoted text clipped - 21 lines] > > That's how I see that. Am I missing something? It's dicey to articulate Java's rules because sometimes we see it as a strictly compiled language, and sometimes we explicitly acknowledge its interpretive and reflective capabilities. I was reading the first part of the thread in terms of javac only, as stated by the OP, wherein reflection is not relevant.
Had the topic opened the door to runtime considerations then we'd be in "yeah, but" territory.
-- Lew
Piotr Kobzda - 30 Mar 2007 16:13 GMT >>> However, if you make everything public, you can keep >>> Inner protected. [quoted text clipped - 12 lines] >> >> Hmm... I don't get it -- there is no any inconsistency IMHO. Ah, I see that now! Daniel is talking about inconsistency with general access rules between the same level outer and inner classes -- which I completely agree with (don't mind here, how that access is implemented!). I, by mistake, tried to apply Daniel's point into the OP's particular case, taking as outer class the SecondLevel class (not even sure now, if it's legal to call it outer?). So, that part is clear now.
>> AIUI, the Inner class is a member of TopLevel class, and as a member >> (not a ?namespace?) is inherited by/into the SecondLevel class. [quoted text clipped - 10 lines] > of the thread in terms of javac only, as stated by the OP, wherein > reflection is not relevant. Sure. However, I'm not really care about reflection here.
> Had the topic opened the door to runtime considerations then we'd be in > "yeah, but" territory. Oh, not really. My confusion expressed here is Java language level related.
For me, each inner class is _a member_ of the class immediately enclosing it, and just like other members (i.e. fields, and methods), is inherited by subclasses of that enclosing class.
Daniel said, that inner class is not inherited, and that's what I'm trying to argue with.
piotr
Piotr Kobzda - 30 Mar 2007 08:19 GMT >> Actually, I think the problem is with your import statements: >> Change them to: [quoted text clipped - 4 lines] > > no, that doesn't solve it... It does. Moreover, it solves most important problem. Even when all Inner's members are public, and both above imports holds, the compiler complains with:
SecondLevel.java:4: somePackage.TopLevel.Inner has protected access in somePackage.TopLevel import somePackage.TopLevel.Inner; ^ 1 error
So the above change is required to solve other problems.
After having it solved you can choose from different solutions of accessing Inner's members (make them public, inherit using own inner class, and the like...).
However, I don't understand why the compiler prohibits the second import? Importing something doesn't implies any access violation on its use, does it?
Is there some reasonable explanation for that prohibition?
piotr
visionset - 29 Mar 2007 22:01 GMT >>If I simply make TopLevel.Inner a public class, the errors go away. But I >>don't really want to do that... > > Check that... I have to make *everything* in the Inner class public to > resolve all the errors. And by doing that I no longer need to import the > Inner class either... Inner is only accessible to members of the same package or any subclass. You are not in the same package and you have no subclass of Inner.
 Signature Mike W
Lew - 29 Mar 2007 23:15 GMT > Inner is only accessible to members of the same package or any subclass. > You are not in the same package and you have no subclass of Inner. What about
> public class SecondLevel extends TopLevel from the original post?
I, too, am surprised that Inner (not its members, but the class itself) would not be accessible from a subclass.
-- Lew
visionset - 29 Mar 2007 23:22 GMT >> Inner is only accessible to members of the same package or any subclass. >> You are not in the same package and you have no subclass of Inner. > > What about >> public class SecondLevel extends TopLevel > from the original post? I don't see that is relevant. However, when I made the inner class subclass TopLevel.Inner it didn't help, and so now I'm suprised too. I couldn't find anyhing in the JSL that made explicit mention to this. Only the phrase 'not all modifiers apply to all declarations' or some such. I'm aware of this and that the compiler silently ignores superfluous key-wordage all over the place eg public in interface methods.
> I, too, am surprised that Inner (not its members, but the class itself) > would not be accessible from a subclass. > > -- Lew
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|