简体   繁体   English

当引用类型为超类时,子类无法访问超类的受保护方法

[英]Sub-class not able to access the protected method of super-class when the reference is of type super-class

Parent class 家长班

package p1;

public class A {
    protected void display() {
        System.out.println("Displayed");
    }
}

Child class (in another package) 儿童班(另一个包)

package p2;

import p1.A;

public class B extends A {
    public static void main(String[] args) {
        A a = new B();
        a.display();
    }
}

In the child class, if I write B a = new B() , it works fine and displays "Displayed". 在子类中,如果我写B a = new B() ,它工作正常并显示“显示”。

But, the above piece of code in child class where A a = new B() is written, it throws compile time error as 'display()' has protected access in 'p1.A' 但是,在子类中上面的一段代码,其中A a = new B()被写入,它会抛出编译时错误,因为'display()' has protected access in 'p1.A'

I am confused with the protected access modifier now as how it works when the reference type is of parent? 我现在对受保护的访问修饰符感到困惑,因为当引用类型是父类时它是如何工作的?

As I wrote in a comment, you can do this: 正如我在评论中所写,你可以这样做:

package p2;

import p1.A;

public class B extends A {

    public static void main(String[] args) {
        B a = new B();
        a.foo();
    }

    public void foo() {
        display(); // works
        super.display(); // same, but more wordy
        A a = (A)this;
        a.display(); // NOT working !!!
    }

    public void bar(A a) {
        a.display(); // NOT working !!!
    }
}

display() , can be called from subclass (static method is not member method) or in same package like this display() ,可以从子类调用(静态方法不是成员方法),也可以在同一个包中调用

package p1;

public class C {

    public static void main(String[] args) {
        A a = new A();
        a.display();
    }

}

hm, those 嗯,那些

a.display(); // NOT working !!!

are something not really clear to me, see discussion 对我来说不是很清楚,请参阅讨论

A a = new B(); doesn't work because the reference type of a is A and A doesn't expose display() to another package. 不起作用,因为的引用类型aAA不暴露display()到另一个包。

take this example: 举个例子:

public void method(A a){ // defined in some class in a different package
   a.display(); // can't be called from different package as reference type is `A`
}

the compiler here has no way to know whether you'll assign a A or a subtype of A and hence it bails out. 这里的编译器没有办法知道你是否会分配A或一个亚型的A ,因此它捞出。

It will be easier to understand if you forget your example for a second and just focus on the method i've created, notice that i'm saying it's in a class defined in a different package. 如果你忘记你的例子一秒钟并且只关注我创建的方法会更容易理解,请注意我说它是在不同包中定义的类中。 now ask yourself can i call display() on A from a different package, obviously not it's a protected method. 现在问问自己,我可以从另一个包中调用AA display() ,显然不是一个受保护的方法。

Here is the relevant Language Specification paragraph: 以下是相关语言规范段落:

If the access is by a qualified name Q.Id or a method reference expression Q :: Id (§15.13), where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S. 如果访问是通过限定名称Q.Id或方法引用表达式Q :: Id(第15.13节),其中Q是ExpressionName,则当且仅当表达式Q的类型是S或a时才允许访问S的子类

( 6.6.2.1. Access to a protected Member ) 6.6.2.1。访问受保护成员

In your case, Q is a , and S is B . 在你的情况下, QaSB Since the type of Q is not a subclass of B the access is not permitted. 由于Q的类型不是B的子类,因此不允许访问。

For the explanation on why this restriction was introduced, see Checking Access to Protected Members in the Java Virtual Machine (search for Requirements on Protected Members ) 有关为何引入此限制的说明,请参阅检查Java虚拟机中受保护成员的访问权限 (搜索受保护成员的要求

The motivation behind the restriction on protected access is to prevent almost arbitrary access to protected members of objects [Yel02]. 限制受保护访问的动机是防止几乎任意访问受保护的对象成员[Yel02]。 Suppose that m is a protected, nonstatic field declared in c. 假设m是c中声明的受保护的非静态字段。 Without the restriction, any class x could read the content of the field m of any object of class c, using the following trick: define a subclass s of c (the trick works only if c is not final, hence the “almost” adverb above); 没有限制,任何类x都可以使用以下技巧读取类c的任何对象的字段m的内容:定义c的子类s(该技巧仅在c不是final的情况下有效,因此“几乎”副词以上); declare a method in s that takes an object of class c as argument and returns the content of its m field; 在s中声明一个方法,该方法将类c的对象作为参数并返回其m字段的内容; and have x call this method. 并让x调用此方法。 The restriction on protected access prevents this situation, because s can access the field only if the class o of the object satisfies o ≤ s 对受保护访问的限制可以防止这种情况,因为只有当对象的类o满足o≤s时,s才能访问该字段

Protected methods can only be accessible through inheritance in subclasses outside the package 受保护的方法只能通过包外的子类中的继承来访问

display will be accessible to every subclass AND every class in the same package. 每个子类和同一个包中的每个类都可以访问display

display will be accessible to every class in the same package (not available in children class if there are in a different package) 显示将在同一个包中的每个类都可访问(如果在不同的包中,则不在子类中可用)

A a = new B(); A =新B(); will not work because the reference type of a is A and A will not exposing display() to another package. 将无法工作,因为a的引用类型是A和A不会将display()暴露给另一个包。

Below code will work: 下面的代码将起作用:

package p2;

import p1.A;

public class B extends A {
    public static void main(String[] args) {
        B a = new B();
        a.demo();
    }

    public void demo(){
        display();
    }
}

I think from the link: http://tutorials.jenkov.com/java/access-modifiers.html important statement is 我想从链接: http//tutorials.jenkov.com/java/access-modifiers.html重要声明是

The protected access modifier provides the same access as the default access modifier, with the addition that subclasses can access protected methods and member variables (fields) of the superclass. 受保护的访问修饰符提供与默认访问修饰符相同的访问权限,并且子类可以访问超类的受保护方法和成员变量(字段)。

Here, subclass means subclass reference type only. 这里,子类仅表示子类引用类型。 For parent reference type, the only option left is public. 对于父引用类型,剩下的唯一选项是public。

It is kind of unstated hidden rule. 这是一种未说明的隐藏规则。 Even the IDEs are suggesting to change it to public to access via parent's reference. 甚至IDE也建议将其更改为public以通过父级的引用进行访问。 Weird! 奇怪的!

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

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