Java 为什么另一个包中的子类不能访问受保护的方法?
我有两个不同包中的两个类:Java 为什么另一个包中的子类不能访问受保护的方法?,java,package,subclass,protected,modifier,Java,Package,Subclass,Protected,Modifier,我有两个不同包中的两个类: package package1; public class Class1 { public void tryMePublic() { } protected void tryMeProtected() { } } package package2; import package1.Class1; public class Class2 extends Class1 { doNow() { Class
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()代码>工作
下面的代码无法编译,因为我们没有调用受保护方法的继承版本
Class1 c = new Class1();
c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1
请按照此链接进行更多解释。您使用两个不同的包,并且不通过直接继承访问父属性,而是通过子类中声明的中间父实例(类似于组合)访问父属性。=>这不是受保护的的工作方式
只有直接继承允许访问受保护父级的属性
因此,您可以这样做:
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
关键字的特殊性。根据Java protected Access修饰符定义,在超类中声明为protected的方法只能由其他包中的子类或受保护成员类包中的任何类访问
无法通过创建类的对象来访问受保护的方法。
因此,为了访问受保护的方法,您必须扩展超类。(这说明您的第二次调用是正确的)它可以通过两种方式实现
1。通过创建子类的对象,然后访问父类的受保护方法。
包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。或者直接从子类调用方法
eg tryMeProtected()代码>我相信您误解了包
和受保护
可见性之间的区别
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
将可供同一包中的每个类访问(如果子类位于不同的包中,则在子类中不可用)
同班儿童
不同包装的儿童班
首先,你需要了解两件事:
1) 包“Y”中类“X”的受保护的成员函数可由子类访问,即扩展它的类(即使该子类不在包“Y”中)。所以,
tryMeProtected(); // Showed no error because this was called by class 2 that is the subclass.
2) 如果包“Y”中类“X”的受保护成员函数位于其他包中,则该函数本身无法访问
[一个简单的类比:一只鸟把蛋放在鸟巢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.
受保护的修饰符为1.Package Private 2.0,可以由其他包的子类看到。
现在,关键区别在于:
MyClass1 c = new MyClass1();
c.tryMeProtected();
及
是使用MyClass1引用而不是继承。MyClass1位于不同的包中,此代码不是从MyClass1继承的 在同一个包外部或在同一个包中(当然都是),不仅在同一个包外部,它们还可以通过单独的实例访问,因为它在java中具有与默认值相同的可见性(除了可以在包外部继承的子类)。是的,我同意,我更喜欢这样一句话:“继承受保护的
方法只有在不同的包中才有意义。”;)@Mik378:是的,正确。我已经修改了帖子中的语句。感谢您指出它。:-)此代码不会产生此错误。方法tryMeProtected()根本不存在。你用你发布的代码测试过吗?如果是,它不能像EJP说的那样工作,你有两个不同的名字:tryMePublic和tryMeProtected@CloudyMarble当然,但是带有protected关键字的继承概念的本质是关于不同的包。否则,默认的包范围就足够了。当然:who可以做得更多,可以做得更少
c.tryMeProtected(); // Showed error because this was called by class 1 reference.
// You can also think of it as class 1 cannot inherit itself.
MyClass1 c = new MyClass1();
c.tryMeProtected();
tryMyProtected();