Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / March 2007

Tip: Looking for answers? Try searching our database.

Protected inner classes and inheritance

Thread view: 
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 Magazines

Get 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 ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.