Java - 为什么另一个包中的子类不能通过父类引用访问父类的受保护方法?

4

我有两个不同包中的类:

package package1;

public class ParentClass {
    public void testPublic() {
    }

    protected void testProtected() {
    }
}


package package2;

import package1.ParentClass;

public class ChildClass extends ParentClass {
   void test() {
        ParentClass par = new ParentClass();
        par.testProtected(); // Line 1 : ERROR: testProtected() has protected access in ParentClass
        testProtected();     // Line 2 : No error

        ChildClass ch = new ChildClass();
        ch.testProtected(); // Line 3 : No ERROR
        testProtected();    // Line 4 : No error
    }    
}

我能理解为什么在调用testProtected() -- Line 2没有错误,因为ChildClass继承自ParentClass,可以看到这个方法。

我也能够理解为什么在调用par.testProtected() -- Line 1时会抛出错误,因为par是一个不同的对象,当前对象不能访问其他对象的父类受保护的方法。

但当引用类型为ChildClass时,对象如何访问同一方法ch.testProtected() -- Line 3(其他对象的父类受保护的方法)呢?


不行,在ChildClass中未定义。只在ParentClass中定义为protected。 - Debashish BHARALI
1个回答

7
你看到的错误完全有道理。
当你执行以下操作时:
ParentClass par = new ParentClass();
par.testProtected();

你正在尝试访问ParentClass的受保护方法testProtected,并且以其作为公共API的一部分来调用它。也就是说,你正在从另一个包中调用ParentClass类的受保护方法在该类的实例上。无论它是否在扩展类内被调用,重要的是它是从另一个包中被调用的。
现在,如果你这样做:
ChildClass ch = new ChildClass();
ch.testProtected(); // Line 3
testProtected();    // Line 4

为什么您不会看到任何错误?

在第3行,您正在访问ChildClass的实例内部的方法,在ChildClass内这是合法的。即使您在ChildClass中有一个私有方法childMethod,您也可以执行ch.childMethod()

在第4行中,您通过this引用(隐式地)访问testProtected,这意味着它通过ChildClass调用该方法,这也是合法的。

请参阅相关帖子:Java中public、protected、package-private和private之间的区别是什么?(提示:在描述的表格中的最后一行)


1
明白了。总的来说,Protected比定义看起来要复杂一些。定义过于简单化了。而且它与其他访问修饰符不相符。它应该说,“只有自己(这个对象的)父类受保护成员可以在扩展ChildClass成员的不同包中被访问”。而不是陈述一个普遍的语句,“受保护的成员可以通过扩展不同包中的ChildClass进行访问”。 - Debashish BHARALI
@DebashishBHARALI 这个问题也可能出现在私有方法中。如果你有一个类型为 Foo 的类,其中包含一个私有方法 bar(),并且你最终得到了 var f = someFooType(),其中 f 的类型被推断为 ? extends Foo,那么即使你在 Foo 类内部,调用 f.bar() 也会导致编译错误。 - Slaw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接