"methods without access control can be declared more private in subclasses"在 Java 中是什么意思?



在java访问修饰符和继承主题中说了以下4点。more private"在第三点是什么意思?

  1. 方法声明没有访问控制=>可以声明更私有在子类

在没有访问控制的情况下声明的方法=>可以在子类中声明为更私有

It is WRONG。这正好相反。使用任何级别的访问控制声明的方法必须用该级别或更公共的级别重写:在这种情况下,访问级别基类是'default',因此您可以使用publicprotected.重写

与Google文档所说的相反,不能用private.重写参见JLS§8.4.8.3:

覆盖或隐藏方法的访问修饰符(§6.6)必须至少提供与被覆盖或隐藏方法相同的访问权限,如下所示:

  • 如果覆盖或隐藏的方法是public,,那么覆盖或隐藏的方法必须是public;,否则会发生编译时错误。
  • 如果重写或隐藏方法是protected,,那么重写或隐藏方法必须是protectedpublic;,否则会发生编译时错误。
  • 如果重写或隐藏的方法有包访问权限,那么重写或隐藏的方法不能是private;,否则会发生编译时错误。

(ruso上有俄文翻译)

实际上没有"更多"或"更少"这样的术语。而使用'more/less visible'。

问题中的语句是错误的一个方法不能变得不可见,因为这会破坏Liskov替换原则:

设Φ(x)是关于t类型对象x的可证明性质,则Φ(y)对于S类型对象y应为真,其中S是t的子类型

这是GitHub上的一个repo,它说明了Java中继承包访问方法的所有可能的变体。https://github.com/NickVolynkin/PackageAccessTest

public class Parent {
    //package access
    void foo() {
    }
}
public class ChildPublic extends Parent {
    // Legal
    @Override
    public void foo() {
    }
}
public class ChildProtected extends Parent {
    // Legal
    @Override
    protected void foo() {
    }
}
public class ChildPrivate extends Parent {
    // Illegal
    /*
    @Override
    private void foo() {
    }
    */
}
public class SamePackageAccessTest {
    {
        new Parent().foo();
        //these have overriden foo()
        new ChildPublic().foo();
        new ChildProtected().foo();
        //this one had not overriden foo()
        new ChildPrivate().foo();
    }
}
package otherpackage;
import test.*;
public class OtherPackageAccessTest {
    {
        //Legal!
        new ChildPublic().foo();
        //illegal
        /*
        new ParentPackage().foo();
        new ChildProtected().foo();
        new ChildPrivate().foo();
        */
    }
}

完整的信息可以在本Java教程

中找到在没有访问控制的情况下声明的

方法可以在不在同一包中的子类中重新定义(这里用"覆盖"这个词不太正确)。

package p1;
public class A {
    void m() {}
}

package p1;
public class B {
    //This does not work as class is in the same package and this would be an attempt to reduce visibility
    private void m() {}
}

package p2;
public class C extends A {
    //This works fine as class C does not 'see' the parent method
    private void m() {
    }
}

最新更新