当前位置:编程学习 > JAVA >>

百思不得其解: 一道继承加权限的题目

跨包继承,有一道题目,请高手帮忙解释一下,不胜感激

父类:
package com.ocjp.acl;

public class Utils {
void do1() { System.out.print("do1 "); }
protected void do2() { System.out.print("do2 "); }
public void do3() { System.out.print("do3 "); }
}


子类:
package com.ocjp.extend;

import com.ocjp.acl.Utils;

public class UPS extends Utils {
public static void main(String[] args) {
Utils u = new UPS();
UPS ups = new UPS();
// default是包级访问权限,跨包访问会报编译错误;
// u.do1();

// 为什么访问protected的方法,也会报编译错误???
// u.do2();

// 这样写是可以的,跟上面的写法有什么不同???
ups.do2();
u.do3();

}

继承 ocjp Java --------------------编程问答-------------------- --------------------编程问答-------------------- 这个好解释。
还是那句话,编译器没有那么智能。
假设有一个类这样:
package com.ocjp.extend2;
 
import com.ocjp.acl.Utils;
 
public class UPS2 extends Utils {
  @Override
  protected void do2(){ System.out.print("overridden do2 "); }
}


在你的main函数里这么写:
UPS2 ups2 = new UPS2();
ups2.do2(); //报错

这显然是不合理的,因为UPS2和UPS一点关系都没有,它们在不同的包,互相没有直接联系,仅仅继承了同一个类而已。
那么在这个前提之下,这样写应该也是不合理的:
Utils u2 = new UPS2();
u2.do2(); //报错

道理一样,u2在编译器眼里也只是一个属于另一个包的类的实例而已。编译器在赋值语句之后,并不会看赋值语句右边是什么,它编译的依据仅仅是赋值语句左边的类型。

在这样的前提下,如果u.do2();合理,那就会存在一个悖论:
如果你能访问u.do2(),那必然能访问u2.do2();,因为编译器只看变量类型。
实际上,u2.do2()是UPS2的一个protected方法,UPS这个类既没有继承UPS2,也不在UPS2的同一个包里,却能通过改变引用类型做越权访问,这显然是不合理的。
所以编译器就会直接拒绝接受像u.do2();这样的语句。而ups.do2();就没有歧义了。Java的对象继承哲学是:你爹做得到的,你一定能做到。所以如果你把你的main搬到Utils里,那就都合法了。 --------------------编程问答-------------------- 我觉得这个很好解释呢:
对象u(com.ocjp.acl)是在它的子类(com.ocjp.extend2)下创建的 
所以在包(com.ocjp.extend2 )对象u访问不到u.do1和do2
而对象ups 则继承了 Utils中的所有非私有方法 创建的对象也是在本包中 所以可以访问 --------------------编程问答--------------------
引用 3 楼 yao752915708 的回复:
我觉得这个很好解释呢:
对象u(com.ocjp.acl)是在它的子类(com.ocjp.extend2)下创建的 
所以在包(com.ocjp.extend2 )对象u访问不到u.do1和do2
而对象ups 则继承了 Utils中的所有非私有方法 创建的对象也是在本包中 所以可以访问

如果你再新建一个类(另外建立一个包), 将main方法移过去 usp.do2也会报错的!
补充:Java ,  Java SE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,