0

Here's my code

Package a

package a;

import static net.mindview.util.Print.print;

import b.B;

public class A
{
    protected void f()
    {
        print("This is A's protected f()");
    }

    public static void main(String[] args)
    {
        // new B().f() does not work!
        // compiler will complain B.f() is not visible
        A a = new B();
        a.f();    //  but using polymorphism here! I can invoke B.f()!
    }
}

Package b

package b;

import static net.mindview.util.Print.print;

import a.A;

public class B extends A
{
    protected void f()
    {
        print("This is B's protected f()");
    }
}

The problem is a.f() in main() actually invokes the class B's protected overridden f() to which class A has no access.

Notice that A is B's superclass, and they are in different packages. A has no access to B's f().

Technically speaking, B's protected f() can only be accessed either from its subclasses or classes in the same package.

But neither condition is satisfied by class A.

So, my question here is does polymorphism actually break the rule of protected access modifier, or is there any implicit and hiding mechanism taking place during the call?

Can anybody help?

Thanks a lot.

The printing result is "This is B's protected f()".

It is a totally different question from "Understanding java's protected modifier". Please look at the code carefully!!!!

In that question, C -> A relationship. in C(subclass) create an A a = new A() (superclass), and tries to access a's protected member but fails to do so.

In my question, B -> A relationship. in "A"(superclass) create an "B" b = new B() (subclass), and tries to access b's protected member(which should not succeed) but succeeds to do so!

I think I express the difference so clearly, for any impatient programmers to quickly distinguish between two questions.

Sai
  • 17
  • 2
  • You just don't understand it correctly. You created a `B` instance. Its function overrides `A` function, so when you run the instance's code, that's what you run. If you don't want this to happen, use `private`, not `protected`. – UDKOX May 18 '16 at 02:09
  • 1
    @UDKOX They are confused about why `new B().f()` doesn't work within package `a`, while the seemingly same `((A)new B()).f()` does. – Sotirios Delimanolis May 18 '16 at 02:14
  • @UDKOX Apparently you didn't understand my code at all. Maybe you need to really look at the code carefully to understand my question. I understand protected modifier without any problems. My question is not about misunderstanding the meaning of protected. You should see the whole pieces of code more carefully. – Sai May 18 '16 at 02:26
  • @Sai Does my previous comment correctly summarize your confusion? – Sotirios Delimanolis May 18 '16 at 02:31
  • @Sai LOL, what an answer. `// compiler will complain B.f() is not visible` change `a.f();` to `((B) a).foo();`. Magic. Just because you declared it as A, doesn't mean it's A. – UDKOX May 18 '16 at 02:33
  • @ Sotirios Delimanolis My question actually has no relationship with the one you marked as duplicate. Actually it is totally different, but maybe very similar at first sight. Let me clarify here and give you some hint to what is going on. In the question you marked as duplicate, C extends A. C is a subclass of A, and A has the protected member. In C, some code tries to create a superclass A's object, and accesses that object's protected field. It will definitely not work. But my question is vice versa. – Sai May 18 '16 at 02:43
  • @SotiriosDelimanolis I create a subclass B's object in A which is a superclass of B, and successfully access a subclass B's protected member(its f() method). But A is superclass of B, A has no access to B's protected member. By using polymorphism, I can invoke B's protected member from its superclass A, which should have no access to B's protected member. That is my question. – Sai May 18 '16 at 02:49
  • 1
    The vice versa reduces to the same issue and is answered by the accepted answer _Let C be the class in which a protected member is declared [...] **then the access is permitted if and only if the type of E is S or a subclass of S**_. Your class `B` declares (and overrides) the method `f()`. As such, the expression `B.f()` cannot be permitted since `A` where you are trying to use this code is neither `B` nor a subclass of `B`. If you removed the declaration of `f()` in `B`, that code would compile. – Sotirios Delimanolis May 18 '16 at 02:55
  • @SotiriosDelimanolis My question is my code compiles without error. My question is not why the code didn't compile. It is why my code compiles without error when it should be. – Sai May 18 '16 at 03:03
  • 1
    The code you commented out doesn't compile because the Java language specification doesn't allow it. The code you currently have compiles because the Java language specification says so, as the duplicate explains. – Sotirios Delimanolis May 18 '16 at 03:04
  • @SotiriosDelimanolis I think u r just too impatient to look at the piece of codes and my explanation down the code carefully. You don't even understand what my question is. How can u mark it as duplicate as a similar but totally different question? – Sai May 18 '16 at 03:07
  • I've reopened. You're going to get the same quote from the JLS. – Sotirios Delimanolis May 18 '16 at 03:07
  • 1
    Your misunderstanding is about `protected` the same way the duplicate is. This is about declaration of members and the type of the target access/invocation expression. – Sotirios Delimanolis May 18 '16 at 03:09
  • Duplicate of [Understanding Java's protected modifier](http://stackoverflow.com/q/18573016/207421). – user207421 May 18 '16 at 03:21
  • @SotiriosDelimanolis My question is why I can access protected method of B in A which is a "superclass" of B. I did not misunderstand protected modifier. Protected modifier specifies only classes of the same package of B or any subclasses S of B can access B's protected method. A is "superclass" of B. A is neither a subclass of B nor in the same package of B. But I invoke B's protected method within A successfully by using polymorphism. Can anybody explain why? – Sai May 18 '16 at 03:29
  • @Sai The only problem here is your misunderstanding of the `protected` modifier. Repeating it over and over again doesn't change anything. The relevant authority here is the JLS, not your (mis)understanding. – user207421 May 18 '16 at 03:43

1 Answers1

1

The problem is a.f() in main() actually invokes the class B's protected overridden f() to which class A has no access.

Wrong. Class A has access to all its own members and their overrides.

Notice that A is B's superclass, and they are in different packages. A has no access to B's f().

You keep saying that, but it's still wrong.

Technically speaking, B's protected f() can only be accessed either from its subclasses or classes in the same package.

Wrong.

But neither condition is satisfied by class A.

They don't have to be satisfied, as you just made them up.

So, my question here is does polymorphism actually break the rule of protected access modifier

No. You have the rule wrong.

or is there any implicit and hiding mechanism taking place during the call?

There is an adherence to JLS #6.6.2.1, which you evidently have not read, and which says:

the access is permitted if and only if the type of E is S or a subclass of S.

You continued:

It is a totally different question from Understanding java's protected modifier.

It is a slightly different question with the same answer. The same rule applies. JLS #6.6.2.1.

Specifically, in your case S is A, E is an implied this, and this is of type B, which is a subclass of A. QED

Community
  • 1
  • 1
user207421
  • 305,947
  • 44
  • 307
  • 483
  • I think we both have some misunderstanding here. I have seen JLS#6.6.2.1 carefully. That just specifies how protected works. My question is not how protected works. I know why new B.f() does not work. I want to know why the polymorphism makes the B's f() can be invoked within A. – Sai May 18 '16 at 04:03
  • @Sai Your `a` is instance of `B`, and in Java, when you have instance of a class, you call methods of that class (in this case `B`). I mean, that's the whole *point* of virtual methods. – hyde May 18 '16 at 04:44