论坛首页 入门技术论坛

javac与protected

浏览 1805 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-09-09   最后修改:2009-09-09
声明:希望大家拍砖,但不要人身攻击

protected:是包和子类可见。但有一个现象很难理解(子类在不同的包中),举个例子。
设计三个类,TObject(基类,其中有个protected void sayHello()方法),TObjectExtends1,TObjectExtends2;
其中TObject和TObjectExtends1在一个包中,TObjectExtends2在另一个包中;
TObjectExtends1和TObjectExtends2继承TObject;然后在TObjectExtends1中运行TObjectExtends2的sayHello()方法。
编译通过,然后运行成功;
然后我在TObjectExtends2中重写了sayHello()方法,权限是protected,然后编译,编译器报错,试图在TObjectExtends1中调TObjectExtends2中受protected方法;
如果把TObjectExtends2 te2=new TObjectExtends2();改成TObject te2=new TObjectExtends2();改一下声明;又居然可以编译通过了,运行成功;

也就是说在不同包的子类中调用其他子类的protected方法,有可以成功(如果调用的子类没有覆盖父类的protected),也有可能失败,如果都声明成最大的那个超类,那都可以运行了,貌似是编译器的错,

测试代码:
TObject:
package extends1;


public class TObject {
	
	/**
	 * Method TObject
	 *
	 *
	 */
	public TObject() {
		// TODO: Add your code here
	}
	
	protected void sayHello(){
		
		System.out.println("TObject");
		
		}	
}



TObjectExtends1:
package extends1;
import extends2.*;

public class TObjectExtends1 extends TObject {
	
	/**
	 * Method TObjectExtends2
	 *
	 *
	 */
	public TObjectExtends1() {
		// TODO: Add your code here
	}
	public static void main(String[] args){
		
		   TObject te2=new TObjectExtends2();
		   te2.sayHello();
		   // TObjectExtends2 te2=new TObjectExtends2();
		   // te2.sayHello();编译通不过
		   
		
		}	
}


TObjectExtends2:
package extends2;
import extends1.TObject;


public class TObjectExtends2 extends TObject {
	
	/**
	 * Method TObjectExtends1
	 *
	 *
	 */
	public TObjectExtends2() {
		// TODO: Add your code here
	}
	
	@Override

	protected void sayHello(){
		
		System.out.println("TObjectExtends2");
		
		}	
		
		
}






   发表时间:2009-09-09   最后修改:2009-09-09
在main方法里面,是不存在具体的某个类,因而没有类继承的可见性,只有包的可见性。

因而:
TObject te2=new TObjectExtends2();   
           te2.sayHello();   



当前main所在的类与te2的声明类在同一包里,因而是正确的调用,可以通过编译。

第二种情形,main所在类与te2的声明类不在同一个包,因而不能编译通过。
0 请登录后投票
   发表时间:2009-09-09  
= =!不明白楼主想说的是什么?
0 请登录后投票
   发表时间:2009-09-09  
首先谢谢大家的回复
dengtl 写道
在main方法里面,是不存在具体的某个类,因而没有类继承的可见性,只有包的可见性。

我对你的解释有点疑问:
如果在main方法中没有继承的可见性,那我把那个代码放到另一个方法中应该可以了吧;但编译还是通不过。
package extends1;
import extends2.*;

public class TObjectExtends1 extends TObject {
	
	/**
	 * Method TObjectExtends2
	 *
	 *
	 */
	public TObjectExtends1() {
		// TODO: Add your code here
	}
	public void mainTest(){
	
		TObjectExtends2 te2=new TObjectExtends2();//[color=red]编译通不过[/color]
		te2.sayHello();
	
	}
	public static void main(String[] args){
		
		   //TObject te2=new TObjectExtends2();
		   //te2.sayHello();
		    // TObjectExtends3 te3=new TObjectExtends3();
		   	// te3.sayHello();
		   	TObjectExtends1 te1=new TObjectExtends1();
		   	te1.mainTest();
		   
		
		}	
}



难道你说的是对于编译器来说继承的可见性是没有的吗?但在子类中可以调父类的properted的域和方法(子类和父类不在同一个包),希望你详细介绍。
我觉得编译器是不允许一个基类的兄弟子类之间相互调protected的域和方法,如果我们用基类,编译器的语法检查可以通过了,但解释器遇到这个时他会用动态绑定来找到子类的那个方法;希望大家谈谈自己的看法

0 请登录后投票
   发表时间:2009-09-11  

我也觉得有点多态的意思,使用父类的引用,调用protected方法,编译器能够通过。

在执行的时候,由于父类的方法被子类2给覆盖了,所以执行子类2的方法。

 

我只能理解到这个层次上了,再深入就不知了

0 请登录后投票
   发表时间:2009-09-11  
多态的原因

  你按照t2来声明,t2的sayHello只对直接继承对象有可见性,所以main方法不可以调用。

  按照父类声明,TObject的sayHello是任意可见的,main方法可以调用,但是是调用哪一个方法是由实例子类决定的,这里T2是实例,t2覆盖了夫类sayHello()方法,相当于sayHello对于TObject是可见的,所以最后结果是TObjectExtends2的sayhello被调用

可以这样理解,TObjectExtends2的sayhello对mian不可见,但是对T1可见,就像你不能学生听话,好好写作业,可以叫家长,家长能让学生好好写作业

java里面有个规定,就是从夫类到子类,方法的可见性应该逐渐放开,而不是逐渐缩小

否则就会有你现在的尴尬,虽然声明为protect,但是封装性依旧被继承破坏了
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics