14.私有的属性不是不继承吗?子类实例变量连属性都没有,光有set,get方法怎么访问的?

1.背景:有些人认为子类在调用从父类继承过来的get方法的时候主体是子类对象,子类对象调用getName(),那么在内部的return name,也就是return this.name,但是子类对象明明是无法访问父类对象的私有成员属性的啊,这是为何?

2.父类User类,子类Student类继承User类,测试类Test01。(请关注注释)

public class User {
	
	private String name;

	//因为创建子类对象的时候,肯定是先调用父类构造方法开辟父类中属性(name)的存储空间
	//因为该方法是公有的可以被子类对象继承(继承是发生在对象级别的),所以子类对象可以调用该方法
	//子类(Student类)对象调用该方法的时候,该方法中的this就是子类对象的引用(因为谁调用该方法this就是谁)
	//所以通过子类对象去调用该方法的时候,这里的this.name是“当前对象.name”,显然当前对象this是子类对象,子类对象中没有name属性(子类不会继承父类的私有属性),所以应该会报错,因为子类对象中并没有name属性。
	//但是这里的“this.name”并没有报错,是因为这里的this.name不是“子类引用.name”而是“父类引用.name”。虽然是用子类对象调用的,但是子类中没有name属性,父类中有name属性,编译器检测到此处需要一个父类对象(因为子类对象可以当成是父类对象)
	//所以这个子类(Student类)对象可以自动上转型为父类(User类)对象(子类对象可以自动转换成父类对象对象上转型),所以子类中虽然没有name属性,但是这里的“this.name”可以正常运行(因为是“父类引用.name”)。
	//子类对象可以当成是父类对象,但是父类对象不可以当成子类,因为一个父类可以被多个子类继承(例如猫类继承动物类,猫类是一个子类,动物是一个父类,可以说猫是一个动物,不能说动物是一个猫)
	//因为用学生(子类)对象调用的该方法,所以可以说是访问的是学生的姓名(子类属性),也可以说访问的是用户的姓名(父类属性),反正name只有一块内存空间,访问的也就只能是这唯一的一块内存空间。
    //子类继承父类除了构造方法之外的所有东西,只不过因为private修饰的属性作用域的问题在子类中无法直接访问父类的私有属性,(直接访问的意思是“子类引用.父类私有属性”)因为private修饰的属性只能在本类中本类的对象访问(即使是在本类中由本类的当前对象强换成子类对象也不能直接访问,虽然在本类中但也不能这样访问,说明了子类对象不可见父类的私有属性,必须由父类对象去调用父类的私有属性),也可以理解为只能由本类对象引用调用(因为对象是属于类的,比如人属于人类)。

	public String getName() {
		return this.name;
	}
	public void setName(String name) {
		User.this.name = name;
	}
	
}
public class Student extends User {}
public class Test01 {
	
	public static void main(String[] args){

		Student s = new Student();//一个学生(子类对象)
		//用学生对象调用父类继承过来的setName方法设置学生的姓名
		//此时setName方法中的this就是s,但是s没有name属性,
		//所以就要进行对象上转型,因为子类对象可以当成是父类对象,将Student类对象转换成User类对象
		//结论:用子类对象调用的话,其中需要有一个隐式类型转换
		s.setName("zhangsan");
		System.out.println(s.getName());//zhangsan
		//如果用父类型的引用指向子类对象,再调用setName方法执行的过程当中,先看User引用指向的是一个什么对象,比如此处指向的是一个子类实例,在运行阶段首先去子类中查找有没有该方法。【并不是说父类引用去调用的某个方法就从父类开始查找,父类的引用指向子类对象,引用中存放的都是地址,无论是父类对象地址也好,子类对象地址也好,都是一个地址,只是Java允许父类的引用指向子类对象这种语法机制,编译期可以通过,称为静态绑定】
		User u = s; //同一个对象,孩子肯定是他爹类型的,所以编译可以通过,编译器允许这种语法
		u.setName("lisi");//因为u是父类对象的引用,所以只能“点”出来父类中有且可以访问到的东西,这样编译才可以通过
		System.out.println(s.getName());//lisi
		
	}
	
}

理解:子类继承父类除了构造方法之外的所有东西,只不过因为private修饰的属性因作用域的问题在子类中无法直接访问父类的私有属性(因为继承是发生在对象级别的,所以所有子类对象都无法访问父类对象的私有属性),私有属性是通过在父类类体中“父类对象引用.父类私有属性”访问的,其他的属性都可以直接通过“子类对象引用.属性名”的方式直接访问。

总结:

1.在父类中将方法中的父类当前对象this强转成子类对象,虽然是在父类类体中的,但是子类对象也无法访问父类的私有成员。【说明了子类对象无法访问父类的私有属性】

2.在子类中将方法中的子类当前对象this转换成父类对象,虽然是父类对象的引用,但是没有在父类类体中也无法访问。【说明了父类的私有属性只能在父类类体中且只能通过父类的引用访问访问】

为什么父类要有私有的属性,又让子类通过接口可以访问,但是又不能直接访问?

比如说小明写了一个“People”类有一个私有的属性idcard(身份证号),并且给idcard属性提供了公开的set和get方法,然后子类是小红写的,有“黑种人类”、“白种人类”,因为小红可能并不知道idcard属性的业务需求,此时小明需要在父类里面规定idcard的访问规范,以防小红在子类直接访问导致出错。所以语法上还是体现封装。理解:“不管是黑种人还是白种人,只要是一个人,他的身份证号就必须遵守一定的规范要求”。

那为什么不在子类中进行约束?

1.每一个子类都可以复用父类的代码,提高代码复用。

2.写子类的人可能不知道该属性的业务需求,需要写父类人员规定好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛英豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值