为什么Java允许提高子类中受保护方法的可见性?

2022-09-02 05:33:28
abstract class Base{
      protected abstract void a();
}

class Child extends Base{
      @Override
      public void a(){
          //why is this valid
      }
}

为什么我们不能降低可见性,但可以提高可见性?

此外,我需要实现模板模式,其中可见的公共方法只能是基类。

例:

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
      }
}

现在,如果java允许提高可见性,那么有两种方法可以公开显示??

我知道界面是一种解决方案,但还有其他方法吗???


答案 1

为什么不允许降低可见性已经在其他响应中进行了解释(这会破坏父类的契约)。

但是,为什么允许增加方法的可见性呢?首先,它不会违反任何合同,因此没有理由不允许它。有时,当在子类中对不受保护的方法有意义时,它可能很方便。

其次,不允许它可能会产生副作用,即有时无法同时扩展类并实现接口:

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

关于你的第二个问题,你对此无能为力。您必须相信实现子类的人不会执行任何破坏您的实现的事情。即使java不允许增加可见性,这仍然不能解决您的问题,因为可以创建具有不同名称的公共方法来调用抽象方法:

class Child extends Base{
      @Override
      protected void a(){

      }

      public void a2() {
           a(); //This would have the same problems that allowing to increase the visibility.
      }
}

答案 2

如果基类对可见性做出承诺,则子类不能打破该承诺,并且仍然满足Liskov替换原则。在承诺方法公开的任何情况下,如果该承诺被破坏,则不能使用子类。

子类 IS-A 基类。如果基类公开了一个方法,那么子类也必须公开。

在Java或C++中没有出路。我猜C#也是如此。


推荐