abstract class Base{
protected abstract void a();
}
class Child extends Base{
@Override
public void a(){
//why is this valid
}
}
Why is that we can't reduce the visibility but can increase it?
Also I need to implement Template pattern in which the public methods visible can only be of base class.
Example:
abstract class Base{
public void callA(){
//do some important stuff
a();
}
protected abstract void a();
}
class Child extends Base{
@Override
public void a(){
//why is this valid
}
}
Now if java allows to increase visibility then there are two methods visible publicly??
I know interface is one solution but is there some other way out???
Asking for help, clarification, or responding to other answers. Making statements based on opinion; back them up with references or personal experience.
Protecting a constructor prevents the users from creating the instance of the class, outside the package. During overriding, when a variable or method is protected, it can be overridden to other subclass using either a public or protected modifier only.
There is absolute no way this can be done. You cannot call a private method of a class from any other class(be it the extending class). It can only be accessed inside that class itself.
By default, the variables and methods of a class are accessible to members of the class itself and to other classes in the same package. To borrow from C++ terminology, classes in the same package are friendly. We'll call this the default level of visibility.
Why decreasing visibility is not allowed is already explained in other responses (it would break the contract of the parent class).
But why it is allowed to increase the visibility of a method? First, it would not break any contract, so there is no reason to not allow it. It can be handy sometimes, when it makes sense in the child class for a method to not be protected.
Second, not allowing it could have the side effect of making impossible sometimes to extend a class and implement an interface at the same time:
interface Interface1 {
public void method();
}
public class Parent {
protected abstract void method();
}
public class Child extends Parent implements Interface1 {
@Override
public void method() {
}
//This would be impossible if the visibility of method() in class Parent could not be increased.
}
About your second question, you can do nothing about it. You have to trust that the person who implements the child class doesn't do anything that breaks your implementation. Even if java wouldn't allow to increase visibility, that would still not fix your problem, because a public method with a different name could be created that calls the abstract method:
class Child extends Base{
@Override
protected void a(){
}
public void a2() {
a(); //This would have the same problems that allowing to increase the visibility.
}
}
If the base class makes a promise regarding visibility, then the subclass cannot break that promise and still satisfy the Liskov substitution principle. You can't use a subclass in any situation where the promised method is exposed if that promise is broken.
The subclass IS-A base class. If the base class exposes a method, so must the subclass.
There's no way out in Java or C++. I'd guess the same is true in C#.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With