简体   繁体   中英

Java: Cannot access protected methods of nested class subclass in subclass of outer class

I'm decomposing a class to allow for reuse, different info-hided implementations etc.

It was:

public class Outer
{
    public static class Inner
    {
        // ...
        protected static void innerDoSomething()
        {
            // ...
        }
    }

    public outerDoSomething()
    {
        //...   
        Inner.innerDoSomething();
        //...
    }
}

And all was well and good, since the outer Outer class is allowed to access protected members of nested Inner class.

But trying to decompose as such:

public class SuperOuter
{
    public static class SuperInner
    {
        // ...
        protected static void innerDoSomething()
        {
            // ...
        }
    }

    // ...
}

public class SubOuter extends SuperOuter
{
    public static class SubInner extends SuperInner
    {
        // ...
        protected static void innerDoSomethingElse()
        {
            // ...
        }
    }

    public outerDoSomething()
    {
        //...   
        SubInner.innerDoSomethingElse(); // OK
        SubInner.innerDoSomething();     // Error: cannnot access!
        //...
    }
}

innerDoSomething() is not accessible, even if protected members of SubInner are accessible by SubOuter, and all protected members of SuperInner should be part of SubInner protected interface.

The only way to make it work, seems to be to add explicit delegation for each method, such as:

    public static class SubInner extends SuperInner
    {
        // ...
        protected static void innerDoSomethingElse()
        {
            // ...
        }

        protected static void innerDoSomething()
        {
            SuperInner.innerDoSomething();
        }
    }

Which is annoying, error-prone and time-wasting. I'm tempted to just declare innerDoSomething() as public, but it's not really correct since it's meant to be used only by SubOuter and its subclasses.

How come? Shouldn't innerDoSomething() protected access be ihnerited and accessibile by SubOuter?

The protected method cannot be access from different package through variable reference. It will work if the two classes SuperOuter and SubOuter will be in the same package.

OK, I think I got around it, carefully re-reading Gosling's The Java Programming Language, 4th ed :

  1. SuperOuter and SubOuter are in different packages, as they logically should be, so there's no blanket whole-package protected members accessibility in place.

  2. Access to protected member of a nested class is actually intended as a special means of access between outer and nested classes (see Chapter 5. Nested Classes and Interfaces )

  3. Yet, protected member accessibility is not simply transitive : apart form nested/outer grant, you need to both to be in a subclass and have a reference that is at least of the type of that subclass (ie at least SubXXX, SuperXXX is not enough), because, I quote paragraph 3.5. What protected Really Means :

Each subclass inherits the contract of the superclass and expands that contract in some way. Suppose that one subclass, as part of its expanded contract, places constraints on the values of protected members of the superclass. If a different subclass could access the protected members of objects of the first subclass then it could manipulate them in a way that would break the first subclass's contract and this should not be permissible.

So, even if in my case xxxInner are meant to logically be part of xxxOuter, and SubOuter extends SuperOuter so the former logically should be able to access any protected members of the latter, still SubOuter cannot access protected members of SuperInner in SuperOuter just in the same way as it couldn't if it had received a SuperInner as an argument to a parameter, because that argument could belong to a completely different hierarchy ramification . There's no specific provision in the language to make the connection in this case.

This also explains why explicit delegation works: SubOuter has access to protected members of SubInner, because outer/nested grant, and SubInner has access to protected members of SuperInner because of extension, but SubOuter cannot access protected members of SuperInner because the latter could actually belong to a different hierarchy ramification, and it's SubInner's job to make the connection , so to say.

Explicit delegation respects everything of the above, logically and by language definitions, so it should be the "correct" way to go, considering proper access, but it's error-prone in implementation because of redundancy (what if I invoke SuperInner.innerDoSomethingElse() inside SubInner.innerDoSomething()?)

Ultimately: I could automate the explicit delegation with some python scripting, for example (I did to automate creation of Builder patterns, which have similar redundancy weakness), or simply renounce to the added safety of access control and make the protected members public.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM