简体   繁体   English

为什么包保护的方法在同一个包中不可见?

[英]Why is package-protected method not visible in the same package?

Assume we have two packages p1 and p2 and classes p1.M1 extended by p2.M12 as follows:假设我们有两个包p1p2以及由p1.M1扩展的类p2.M12 ,如下所示:

package p1;

public class M1 {
    void method1() {
        System.out.println("Method 1 called");
    }
}


package p2;

import p1.M1;

public class M12 extends M1 {
    void method2() {
        System.out.println("Method 2 called");
    }
}

Let's extend M12 with p2.B :让我们用p2.B扩展M12

package p2;

public class B extends M12 {

    public void doSomething()  {
        method1();
        method2();
    }
} 

This gives a compilation error as method1 , being package-protected within p1 is not visible in p2 .这会导致编译错误为method1 ,在p1中受包保护在p2中不可见。 method2 is visible without problems. method2是可见的,没有问题。

Now let's extend p2.M12 with p1.A :现在让我们用p1.A p2.M12

package p1;

import p2.M12;

public class A extends M12 {

    public void doSomething() {
        method1();
        method2();
    }
}

Here I'm getting a compilation error for both method2() (which is understandable) and method1() :在这里,我遇到了method2() (这是可以理解的)method1()的编译错误: 来自类型 M1 的方法 method1 不可见

My question is: why is the method1 which is package-protected in the package p1 is not visible in the class A from the same package p1 ?我的问题是:为什么包p1中受包保护的method1在同一个包p1的类A中不可见?

I think the easiest way to understand this behavior is the idea of "A is a M12"我认为理解这种行为的最简单方法是“A 是 M12”的想法

When you declared the inheritance, you told A to get its behavior from M12, but M12 has no visible method called method1.当您声明继承时,您告诉 A 从 M12 获取其行为,但 M12 没有称为 method1 的可见方法。

Let's do an experiment for fun:让我们做一个有趣的实验:

public class M12 extends p1.M1 {
    public void method1() {
        System.out.println("Method 1 called");
    }
    void method2() {
        System.out.println("Method 2 called");
    }
}

Forget A.. when you declare such method, it is allowed - if you do not have an @Override on it.忘记 A.. 当你声明这样的方法时,它是允许的 - 如果你没有 @Override 就可以了。 however, if M1 was:但是,如果 M1 是:

public class M1 {
    public void method1() {
        System.out.println("Method 1 called");
    }
}

you could have:你可以有:

public class M12 extends p1.M1 {
    @Override
    public void method1() {
        System.out.println("Method 1 called");
    }

    void method2() {
        System.out.println("Method 2 called");
    }
}

now, back to the original code for M1 and M2 with the method re-declared and method one made public:现在,回到 M1 和 M2 的原始代码,重新声明方法并将方法一公开:

public class M12 extends p1.M1 {
    public void method1() {
        System.out.println("Method 1 called");
    }

    public void method2() {
        System.out.println("Method 2 called");
    }
}

Then, you would be able to have然后,您将能够拥有

public class A extends M12 {

    public void doSomething() {
        method1();
        method2();
    }
}

ok, this is a trivial case, but would be missing to complete the sequense... bottom line, semantically, you could explain by the IS relationship.好的,这是一个微不足道的案例,但是会缺少完成序列...底线,从语义上讲,您可以通过 IS 关系来解释。


If more is needed ( https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html ):如果需要更多( https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html ):

The following table shows the access to members permitted by each modifier.下表显示了对每个修饰符允许的成员的访问。

Access Levels访问级别

Modifier    Class   Package Subclass    World

public      Y       Y       Y           Y

protected   Y       Y       Y           N

no modifier Y       Y       N           N

private     Y       N       N           N

First, what is a member of a class?首先,什么是类的成员? The Java Language Specification states Java 语言规范声明

A class body may contain declarations of members of the class, that is, fields (§8.3), methods (§8.4), classes (§8.5), and interfaces (§8.5).类体可能包含类成员的声明,即字段(第 8.3 节)、方法(第 8.4 节)、类(第 8.5 节)和接口(第 8.5 节)。

And what are they composed of?它们是由什么组成的? The JLS states JLS 声明

The members of a class type are all of the following:类类型的成员全部如下:

  • Members inherited from its direct superclass (§8.1.4), except in class Object, which has no direct superclass从其直接超类(第 8.1.4 节)继承的成员,除了没有直接超类的 Object 类
  • Members inherited from any direct superinterfaces (§8.1.5)从任何直接超接口继承的成员(第 8.1.5 节)
  • Members declared in the body of the class (§8.1.6)在类主体中声明的成员(第 8.1.6 节)

It also mentions它还提到

Only members of a class that are declared protected or public are inherited by subclasses declared in a package other than the one in which the class is declared.只有声明为protectedpublic的类的成员才能被声明在一个包中的子类继承,而不是在其中声明该类的那个。

All of this is reworded in the chapter on Inheritance所有这些都在继承一章中重新表述

A class C inherits from its direct superclass all concrete methods m (both static and instance) of the superclass for which all of the following are true:C从其直接超类继承父类的所有具体方法m (包括静态方法和实例方法),满足以下所有条件:

  • m is a member of the direct superclass of C . mC的直接超类的成员。
  • m is public , protected , or declared with package access in the same package as C` . mpublicprotected在与 C` 相同的包中声明为具有包访问权限
  • No method declared in C has a signature that is a subsignature (§8.4.2) of the signature of m . C中声明的任何方法都没有作为m签名的子签名(第 8.4.2 节)的签名。

The members of class M1 are method1 (and all the methods of Object ).M1的成员是method1 (以及Object的所有方法)。 M12 , being in a different package than its direct superclass, M1 , does not inherit method1 . M12与其直接超类M1位于不同的包中,因此不会继承method1 The members of M12 are therefore only method2 .因此M12的成员只是method2

The direct superclass of B is M12 and is in the same package. B的直接超类是M12并且在同一个包中。 It therefore inherits its member, method2 .因此它继承了它的成员method2 B knows nothing about method1 . Bmethod1一无所知。 If you had compiled your code with javac , you would have received a cannot find symbol compilation error instead.如果您使用javac编译了代码,您将收到一个cannot find symbol编译错误。 (It seems Eclipse is trying to guess what you were trying to do.) (似乎 Eclipse 试图猜测您要做什么。)

Similarly, the direct superclass of A is M12 , but is in a different package.同样, A的直接超类是M12 ,但在不同的包中。 It does not inherit method2 for that reason.由于这个原因,它不继承method2 A doesn't know anything about method1 or method2 because it didn't inherit them. Amethod1method2一无所知,因为它没有继承它们。 Both of those symbols cannot be found.这两个符号都找不到。

Visibility must flow through the class hierarchy.可见性必须流经类层次结构。

The class hierarchy is A --> M12 --> M1类层次结构是A --> M12 --> M1

The since M1.method1 is not visible to M12 , it's not visible to any subclasses of it either, like A .由于M1.method1M12不可见,因此它的任何子类也不可见,例如A

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM