为啥另一个包中的子类不能访问受保护的方法?
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】:
我相信您误解了package
和protected
可见性之间的区别。
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
【讨论】:
【参考方案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
确实,这是protected
keyword 的特殊性,经常被误解。
【讨论】:
@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 - 为啥另一个包中的子级无法通过父级引用访问父级的受保护方法?