为什么派生类重写方法不应该比java中的基类更具限制性?

Ros*_*ose 17 java

为什么派生类重写方法不应该比java中的基类更具限制性.为什么编译器抛出错误?你能解释一下原因吗?

Jon*_*eet 29

关键是,只知道你的超类的调用者应该仍然可以使用它给出的子类的任何实例.考虑这种情况:

public class Super
{
    public void print()
    {
        System.out.println("Hello!");
    }
}

public class Sub extends Super
{
    @Override
    void print() // Invalid
    {
        System.out.println("Package access");
    }
}
Run Code Online (Sandbox Code Playgroud)

现在从一个不同的包,想象我们有:

public void printSuper(Super x)
{
    x.print();
}
Run Code Online (Sandbox Code Playgroud)

我们称之为:

printSuper(new Sub());
Run Code Online (Sandbox Code Playgroud)

你期望做什么?你覆盖了这个方法,所以它应该打印"包访问" - 但这意味着你要从另一个包调用一个包访问方法......

基本上,这只是Liskov替代原则的一个例子.您应该能够将子类的任何实例视为超类的实例,并且很难看出它如何适应在子类中使事情更具限制性.

  • 你可以引用利斯科夫替代原则http://en.wikipedia.org/wiki/Liskov_substitution_principle (5认同)
  • @JonSkeet我很懒,为了说明这一点,我没有写一个新的答案所以我只是添加了一个提醒 - 知道你的声誉我不应该怀疑你会添加它:-) (2认同)

JRR*_*JRR 6

您不能使访问修饰符更具限制性,因为这会违反继承的基本规则,即子类实例应该可替换超类实例.

例如,假设Person类具有许多类(包括非子类)正在使用的getName公共方法.但是有人刚刚将Employee添加为Person的子类,而Employee中的getName受到保护,只能通过子类访问以前的代码将开始破坏,而Employee将无法替换为Person对象.

因此java决定强制进行这种重新定位.