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

bksxznpy  于 2023-01-24  发布在  Java
关注(0)|答案(8)|浏览(319)

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

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对象上的这个方法呢?

6ojccjat

6ojccjat1#

受保护的方法只能通过包之外的子类继承来访问,因此tryMeProtected();的第二种方法是有效的。
下面的代码无法编译,因为我们没有调用protected方法的继承版本。

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

有关详细说明,请访问此stackoverflow链接。

bxjv4tth

bxjv4tth2#

我相信您误解了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"); }
}
  • tryMePublic无论您身在何处都可以访问。
  • tryMeProtected对于同一个包中的每个子类和每个类都是可访问的。
  • 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
    }    
}
bkkx9g8r

bkkx9g8r3#

你使用了两个不同的包,并且你不是通过直接继承来访问你的父属性,而是通过一个在子类中声明的中间父示例(类似于composition)。=〉这不是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
    }    
}

的确,这是protected关键字的一个特殊性,经常被误解。

hrirmatl

hrirmatl4#

首先,你需要了解两件事:
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.
mzmfm0qo

mzmfm0qo5#

根据Java保护访问修饰符定义,在超类中声明为受保护的方法只能由其他包中的子类或受保护成员类的包中的任何类访问。
你不能通过创建类的对象来访问受保护的方法。所以为了访问受保护的方法,你必须扩展超类。(这说明你的第二次调用是正确的)

siv3szwd

siv3szwd6#

它可以通过两种方式实现

1.生成Child类的对象,然后访问Parent类的受保护方法。

包1

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

Package 2

public class Class2 extends Class1 {

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

2.或者直接从Child类调用方法

eg tryMeProtected();

xam8gpfp

xam8gpfp7#

protected修饰符是1.包私有2.可以被其他包的子类看到。现在说明以下两者的主要区别:

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

以及

tryMyProtected();

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

7cwmlq89

7cwmlq898#

你试试这样:-

public class Class2 extends Class1 {
    doNow() {
        
Class2 c = new Class2();
       
c.tryMeProtected(); // No error

tryMeProtected();  //  error
    }

}

相关问题