-2

I have the following code:

package pack1;

public class Father {
    public String met1(){
        return "c ";
    }
    protected String met2(){
        return "b "+met1();
    }
}




package pack2;
import pack1.Father;

class Child extends Father {
    public String met1(){
        return "a ";
    }
}

class GrandChild extends Child {
    public String met2(){
        return super.met2() + "z" ;
    }
    public static void main(String[] args){
        Father f = new GrandChild();
        System.out.println(f.met2()); // Compile error here
    }
}

When I call met2(), it executes the version implemented in GrandChild, that calls to super.met2(), so it executed the version implemented in Child (that is the Father's version, because Child doesn't implements met2()). But why does the compiler say "met2() is not visible" if I'm calling it from GrandChild (subclass of Father, indirectly), when met2() is "protected"? It should recognise met2() because I'm calling it from a subclass and its protected (visible to subclasses)!!

Thank you!

Andrei Sfat
  • 8,440
  • 5
  • 49
  • 69
Joe Barton
  • 29
  • 3

2 Answers2

1

You cannot weaken the privilege from the parent class. Since met2() from Father has protected, you can either override it with protected or with public.

Since you do not specify any privilege access, it defaults to package protected, which is a level weaker than protected.

This is the restriction from the language itself and follows the Liskov substitution principle (LSP)

UPDATE

If Father is in a different package than its "children", you will need to declare met2() as public in order to be able to access it from your subclasses

Andrei Sfat
  • 8,440
  • 5
  • 49
  • 69
  • Ok, but when I change visibility from default to protected (or public), I keep getting the last error: "met2() is not visible". Why? I declared met2() "protected" in Father class, why it's not visible in GrandChild class? – Joe Barton Dec 30 '17 at 11:24
  • @AlanCross - Can you please update the code in your question so that it corresponds to the error message that you say you're getting. – Oliver Charlesworth Dec 30 '17 at 11:24
  • @AlanCross - That code appears to compile fine: https://ideone.com/uqgslj – Oliver Charlesworth Dec 30 '17 at 11:28
  • @OliverCharlesworth, @AlanCross, I've tested in my IDE, besides the `protected` part, I don't get anything related to `met2() is not visible`. Are you sure you are showing all the code? – Andrei Sfat Dec 30 '17 at 11:29
  • Father class is in a package, Child and GrandChild are in another package. When i move Father class to the package of Child and GrandChild, the error dissapears. But I don't know why. I suposed "protected" allows visibility to subclasses (doesn't matter if they are in another package). – Joe Barton Dec 30 '17 at 11:31
  • well, it does matter a lot if they are in different packages. If you did not specify "protected" in one of the methods, trying to call a method from one package to another won't work because, yes, you guessed it, "met2() is not visible". Can you make a realistic example with packages that can simulate what you are experiencing? – Andrei Sfat Dec 30 '17 at 11:33
  • But, if i call met2() in Child class, compiler allows me to proceed. And Child and Father are in different packages. Why I can't do the same in GrandChild class? – Joe Barton Dec 30 '17 at 11:43
  • it's not a problem in GrandChild either. You will get an error when you want to do in the your main method the `Father f = new GrandChild();` bit. `f.met2()` will fail because it has protected access. At least this is what I experienced. Can you tell us where is the exact line of code that you say the compiler/IDE is complaining about? Is it in your `main()` or somewhere else? – Andrei Sfat Dec 30 '17 at 11:48
  • Yes, it's included in main method. It's curious, because main is inside GrandChild class, but I'm sure that's the problem, doing it in main method. Thank you. – Joe Barton Dec 30 '17 at 11:50
0

That is because you cannot reduce the visibility of the subclass methods when overriding.

since m2() in Father class is protected. m2() in GrandChild class cannot have the default access specifier. It should be public or protected but not default as it results in lowering the visibility of the subclass.

Vikram Singh
  • 113
  • 9