weixin_42348476 2009-10-23 02:43
浏览 172
已采纳

关于在继承条件下对包访问权限的一个问题

在James Gosling的《Java程序设计语言(第4版)》(《The Java Programming Language(Fourth Edition)》的第18章——包的访问里关于可访问性和覆盖方法的讨论中,作者对于类中具有包访问权限的方法在继承条件下有这样的观点:

有如下三个类:

/**第一个类的代码*/
package p1;

public abstract class AbstractBase {

private void pri(){System.out.println("AbstractBase .private()");}
void pac(){System.out.println("AbstractBase .package()");}
protected void pro(){System.out.println("AbstractBase .protected()");}
public void pub(){System.out.println("AbstractBase .public()");}

public final void show(){
    pri();
    pac();
    pro();
    pub();
}

}

/**第二个类的代码*/
package p2;

import p1.AbstractBase ;

public class Concrete1 extends AbstractBase {
public void pri(){System.out.println("Concrete1.private()");}
public void pac(){System.out.println("Concrete1.package()");}
pubilc void pro(){System.out.println("Concrete1.protected()");}
public void pub(){System.out.println("Concrete1.public()");}

}

/**第三个类的代码*/
package p1;

import p2.Concrete1;

public class Concrete2 extends Concrete1 {

public void pri(){System.out.println("Concrete2.private()");}
public void pac(){System.out.println("Concrete2.package()");}
public void pro(){System.out.println("Concrete2.protected()");}
public void pub(){System.out.println("Concrete2.public()");}    

}

作者认为由于Concrete1与AbstractBase不在同一个包中,AbstractBase类中具有包访问权限的pac方法不能被Concrete1访问和继承,因此Concrete1类中的pac方法,也不算是覆盖AbstractBase类中的pac方法;由于Concrete2与AbstractBase在同一个包中,Concrete2可以访问继承到AbstractBase的pac方法,因此Concrete2的pac方法既覆盖了Concrete1的pac方法也覆盖了AbstractBase的pac方法。而经验证,在Concrete2的main方法中通过new Concrete2的对象调用AbstractBase类的final方法show的输出结果是:

AbstractBase.private()
Concrete2.package()
Concrete2.protected()
Concrete2.public()

这也表明Concrete2的pac方法的确覆盖了AbstractBase的pac方法。
然后,我对第二个和第三个类进行了如下的改造:

/**第二个类修改后的代码*/
package p2;

import p1.AbstractBase ;

public class Concrete1 extends AbstractBase {
public void pri(){System.out.println("Concrete1.private()");}
pubilc void pro(){System.out.println("Concrete1.protected()");}
public void pub(){System.out.println("Concrete1.public()");}

}

/**第三个类修改后的代码*/
package p1;

import p2.Concrete1;

public class Concrete2 extends Concrete1 {

public void pri(){System.out.println("Concrete2.private()");}
public void pro(){System.out.println("Concrete2.protected()");}
public void pub(){System.out.println("Concrete2.public()");}
    public void show2(){
    pri();
    pac();//该行编译器报错:类型AbstractBase中的方法pac()不可视。
    pro();
    pub();
}

}

如果说Concrete2能够访问继承到AbstractBase中具有包访问权限的方法pac,那么在我进行了以上修改后编译器不应该报错说那个方法不可视。如果说Concrete2不能够访问继承到AbstractBase的pac方法,那么就说明在修改前的代码仅仅是对Concrete1中的pac方法进行的覆盖,而Concrete1中的pac方法又不是对AbstractBase中的pac方法的覆盖。那么修改前的输出应该是:

AbstractBase.private()
AbstractBase.package()
Concrete2.protected()
Concrete2.public()

而不是:

AbstractBase.private()
Concrete2.package()
Concrete2.protected()
Concrete2.public()

我的问题是,在以上三个类的继承关系下,Concrete2是否能真正继承并可访问AbstractBase中具有包访问权限的方法pac,修改前Concrete2是否真的也覆盖了AbstractBase的pac方法?
[b]问题补充:[/b]
首先感谢lovewhzlq,蔡华江两位朋友的及时作答。
但是,对于蔡华江朋友的作答,我仍有个疑问。在第一个例子中,我的确定义的是Concrete2对象。但Concrete2对象本身没有show方法,它是通过调用其隔代超类AbstractBase中的final方法show来调用pac方法的。如果按蔡华江朋友所说的,“。。。调出来的就是Concrete2的pac方法”。那在Concrete2访问不到从而就覆盖不了AbstractBase中的pac方法的情况下,AbstractBase中的show方法为什么调用的是Concrete2中的pac方法而不是本类自身的pac方法呢(请注意AbstractBase类本身是有pac方法的)?就如同,Concrete2无法访问并覆盖AbstractBase中的pri方法。但在同样的调用执行中,show方法却明显调用的是AbstractBase类中的pri方法(同样请注意Concrete2类本身也是有pri方法的);如果Concrete2能访问到并继承了AbstractBase中的pac方法,那在第二个例子中,编译器就不该报错。所以,我关心的重点是:Concrete2中的pac方法与AbstractBase中的pac方法是否构成覆盖关系,而Concrete1仅仅是构成这个问题的一个桥梁和手段。因此,lovewhzlq朋友的回答对于问题理解的偏差也许更大一些,毕竟super只能引用到Concrete1而与AbstractBase无关。
:) 同时欢迎更多的朋友参与我这个小问题的讨论,谢谢

  • 写回答

2条回答 默认 最新

  • CaiHuajiang 2009-10-23 09:11
    关注

    Concrete1不能继承AbstractBase中的pac方法,因此这里不存在继承,也不存在覆盖。
    第一例子中的Concrete1的pac方法,可以完全看成一个新定义的方法,Concrete继承了,并且你定义的是Concrete2对象(这很重要),所以调出来的就是Concrete2的pac方法。
    而第二个例子中Concrete1中没有定义这个方法,Concrete2中也没有这个方法,所以出错。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥15 stable diffusion
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条