【问题标题】:Override a method with more restrictive access modifier [duplicate]使用更严格的访问修饰符覆盖方法[重复]
【发布时间】:2017-12-19 04:17:38
【问题描述】:

我想知道: 为什么覆盖方法不能具有比被覆盖方法更严格的访问修饰符?

例如:

class Animal{
    public void eat(){
        System.out.println("Generic Animal Eating Generically");
    }
}

class Horse extends Animal{
    public void eat(){
        System.out.println("Horse eating hay, oats, and horse treats");
    }
}

在Horse类中,为什么我不能这样写代码:

private void eat(){
    System.out.println("Horse eating hay, oats, and horse treats");
}

protected void eat(){
    System.out.println("Horse eating hay, oats, and horse treats");
}

【问题讨论】:

  • 你应该用@Override 注释一个被覆盖的函数
  • 因为你不能调用Animal animal = new Horse(); animal.eat() 因为eat() 方法是私有的。但是Animal 类将其声明为公开的。这是没有意义的。

标签: java


【解决方案1】:

还记得每个孩子都是父母的原则吗?

假设你已经创建了一个实例

Animal animal = new Horse();

当有人做animal.eat() 现在应该发生什么?

Animal 拥有具有足够权限的eat() 方法,同时您将Horse 中的eat() 的访问权限限制为private,这意味着您只能在Horse 内部访问该方法。无赖。

【讨论】:

    【解决方案2】:

    它违反了多态性原则(子类实例应该可以代替超类实例使用)

    【讨论】:

      【解决方案3】:

      这是 OOP 的主要概念之一Polymorphism

      当您扩展一个类时,您不能限制可见性,因为如果您创建该子类的新实例,则会出现概念错误。

      例子:

      Animal animal = new Horse();
      

      在这种情况下,animal 具有方法 eat 公开但 horse 私有,这不起作用。创建扩展 Animal 的类的实例我希望能够访问 eat 方法。

      否则您可以在子类中扩展方法可见性,例如:

      class Animal{
          protected void eat(){
              System.out.println("Generic Animal Eating Generically");
          }
      }
      
      class Horse extends Animal{
          public void eat(){
              System.out.println("Horse eating hay, oats, and horse treats");
          }
      }
      

      【讨论】:

        【解决方案4】:
        1. 当你说 Horse extends Animal 时,这意味着你正在建立 马是动物

          的关系

          现在假设这是否可能:

          class Animal{
              public void eat(){
                  System.out.println("Generic Animal Eating Generically");
              }
          }
          
          class Horse extends Animal{
              private void eat(){
                  System.out.println("Horse eating hay, oats, and horse treats");
              }
          }
          

          假设,您正在使用此层次结构的第三个类。

           class B{
               Animal animalInstance = new Animal() ;
               animalInstance .eat();
               //other code that use this instance               
            } 
          

          现在,如果你尝试用 Horse 实例替换这个 animalInstance:

            private Horse horseInstance = new Horse();                     
            horseInstance .eat(); // Error! Horse doesn't expose this method to outside world!!
          

          那么这将导致编译时错误。如果动物 实例不能被 Horse 实例替换,那么 Horse Is Not An 动物!您违反了 IS A 关系。

        2. 这还有一个方面。当你说方法覆盖时,它 是运行时多态性。意味着,在运行时,编译器将检查,如果 子类已覆盖此方法,然后应用子行为, 否则父母行为。在上述情况下,它何时会尝试运行 Horse 行为,这将失败,因为 Horse 将其设为私有。

          这种问题在其他情况下不会发生 - 其中 具有较少限制的访问修饰符的子覆盖。

        希望这能消除您的疑虑。

        【讨论】:

          猜你喜欢
          • 2015-11-27
          • 2013-03-17
          • 2012-11-07
          • 1970-01-01
          • 2015-03-06
          • 2014-07-31
          • 2017-11-07
          • 2015-10-14
          相关资源
          最近更新 更多