为啥另一个包中的子类不能访问受保护的方法?

Posted

技术标签:

【中文标题】为啥另一个包中的子类不能访问受保护的方法?【英文标题】:Why subclass in another package cannot access a protected method?为什么另一个包中的子类不能访问受保护的方法? 【发布时间】:2013-11-25 18:59:36 【问题描述】:

我在两个不同的包中有两个类:

package package1;

public class Class1 
    public void tryMePublic() 
    

    protected void tryMeProtected() 
    



package package2;

import package1.Class1;

public class Class2 extends Class1 
    doNow() 
        Class1 c = new Class1();
        c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1
        tryMeProtected();  // No error
        

我可以理解为什么调用tryMeProtected() 没有错误,因为Class2 认为这个方法继承自Class1

但是为什么Class2 的对象不能使用c.tryMeProtected(); 访问Class1 的对象上的这个方法呢?

【问题讨论】:

此代码不会产生此错误。 tryMeProtected() 方法根本不存在。 您是否使用您发布的确切代码对此进行了测试?如果是,它不能像 EJP 所说的那样工作,你有两个不同的名字:tryMePublic 和 tryMeProtected 【参考方案1】:

受保护的方法只能通过在包外的子类中继承来访问。因此,第二种方法 tryMeProtected(); 有效。

下面的代码不会编译,因为我们没有调用受保护方法的继承版本。

 Class1 c = new Class1();
 c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1

点击此*** 链接了解更多说明。

【讨论】:

在外或在同一个包中(当然都是),不仅在外 在同一个包中,它们可以通过单独的实例访问,因为它与 java 中的默认可见性相同(除了可以在包之外继承的子类)。 是的,同意,我更喜欢这样的句子:“protected 方法的继承只对不同的包有意义。” ;) @Mik378 :是的,正确。我已经修改了帖子中的声明。谢谢你指出。 :-)【参考方案2】:

我相信您误解了packageprotected 可见性之间的区别。

package package1;

public class MyClass1 
    public void tryMePublic()  System.out.println("I'm public"); 
    protected void tryMeProtected()  System.out.println("I'm protected"); 
    void tryMePackage()  System.out.println("I'm package"); 

无论您身在何处,都可以访问tryMePublictryMeProtected 将可供同一包中的每个子类和每个类访问。 tryMePackage 将可供同一包中的每个类访问(如果它们位于不同的包中,则子类中不可用)

同包子类

package package1;

public class Class2 extends MyClass1 
    public void doNow() 
        tryMePublic(); // OK
        tryMeProtected(); // OK
        tryMePackage(); // OK
        

不同包中的子类

package package2;

import package1.MyClass1;

public class Class3 extends MyClass1 
    public void doNow() 
        MyClass1 c = new MyClass1();
        c.tryMeProtected() // ERROR, because only public methods are allowed to be called on class instance, whereever you are
        tryMePublic(); // OK
        tryMeProtected(); // OK
        tryMePackage(); // ERROR
        

【讨论】:

【参考方案3】:

您使用两个不同的包,并且您不是通过直接继承来访问您的父属性,而是通过在子类中声明的中间父实例(类似于组合)。 => 这不是protected 的工作方式。

只有直接继承才能访问受保护的父级属性。

因此,您可以这样做:

public class Class2 extends Class1 
    doNow() 
        tryMeProtected();  // No error since direct inheritance 
        

但从来没有这样:

public class Class2 extends Class1 
    doNow() 
        Class1 c = new Class1();
        c.tryMeProtected(); // this is not a direct inheritance! since `c`, although a parent one is an intermediate instance created in the child instance. => bad
        

确实,这是protectedkeyword 的特殊性,经常被误解。

【讨论】:

@CloudyMarble 当然,但是带有protected关键字的继承概念的本质是关于不同的包。否则,默认包范围就足够了。当然:谁可以做得更多,谁就可以做得更少【参考方案4】:

首先,你需要明白两件事:

1) 包'Y'中的类'X'的protected成员函数可以被子类访问,即扩展它的类(即使子类在包中而不是'Y')。这就是为什么,

tryMeProtected(); // Showed no error because this was called by class 2 that is the subclass.

2) 包“Y”中的类“X”的protected 成员函数如果在其他包中,则无法自行访问。

[ 一个简单的类比:一只鸟的蛋放在巢 1 中,它飞到了巢 2。从巢 2 中,它无法访问保存在巢 1 中的蛋。] 同样,如果一个类在另一个包中,则不能访问其成员函数(除非声明为 public。)。

这就是为什么:

c.tryMeProtected();  // Showed error because this was called by class 1 reference.
                     //  You can also think of it as class 1 cannot inherit itself.

【讨论】:

【参考方案5】:

根据 Java Protected Access 修饰符定义,在超类中声明为 protected 的方法只能由其他包中的子类或受保护成员类的包中的任何类访问。

你不能通过创建类的对象来访问受保护的方法。 因此,要访问 Protected 方法,您必须扩展超类。(这说明您的第二次调用是正确的)

【讨论】:

【参考方案6】:

可以通过两种方式实现

1.通过创建 Child 类的对象,然后访问 Parent 类的受保护方法。

包 1

public class Class1 
    protected void m1() 
        System.out.println("m1 called");
    

包2

public class Class2 extends Class1 

    public static void main(String[] args) 
        Class2 class2 = new Class2();
        class2.m1();
    

2。或者直接调用 Child 类中的方法

eg tryMeProtected();

【讨论】:

【参考方案7】:

protected 修饰符是 1.Package Private 2.可以被其他包的子类看到。 现在的主要区别是:

MyClass1 c = new MyClass1();
    c.tryMeProtected();

tryMyProtected(); 

是使用了 MyClass1 引用而不是继承。 MyClass1 位于不同的包中,并且此代码不是从 MyClass1 继承的。

【讨论】:

以上是关于为啥另一个包中的子类不能访问受保护的方法?的主要内容,如果未能解决你的问题,请参考以下文章

Java - 为啥另一个包中的子级无法通过父级引用访问父级的受保护方法?

为啥受保护的修饰符在 Java 子类中的行为不同?

无法访问子类中的受保护方法[重复]

如何在子类中访问超类的“受保护的静态”变量,子类位于不同的包中......?

为啥我不能访问静态多态派生类中的受保护成员?

在 Java 中,为啥可以从同一个包中的类外部访问受保护的成员? [复制]