封装是面向对象的基础; 继承是在封装的基础上,实现代码的复用性;
创新互联专注于尤溪企业网站建设,成都响应式网站建设,商城开发。尤溪网站建设公司,为尤溪等地区提供建站服务。全流程按需求定制设计,专业设计,全程项目跟踪,创新互联专业和态度为您提供的服务而多态考量的是代码的丰富度。
多态的含义:相同的行为,不同的实现。
(比如:买菜,买青菜买白菜都是买菜行为)
条件:
1.有继承
2.有同名方法
注意:
1、多态指的是行为的多样性,没有属性多态这一说;
2、相同的行为指的是同名方法,也就是说方法名相同,我们就认为这是相同的行为。
由此,我们前面学习的方法重载和方法重写其实都是(静态)多态的表现。
在编译期间就可以确定要执行的是何种类型的对象以及该对象的何种行为,运行期不会有改变的情况。
我们在前面学过的方法的重载和方法的重写都是属于静态多态。静态多态虽然有丰富度的体现,但是是不够的,因为它在编译期就把执行效果固定下来了。而我们以后用得更多的是动态多态。
动态多态在运行期,根据绑定对象的不同,才能确定多态方法执行的效果。
动态多态是由两个技术合并使用才有的效果:动态绑定技术 + 方法的重写。
动态绑定技术 从现象上看效果:本类引用 指向 本类对象;
父类引用 指向 子类对象;
在Java当中只有这两种情况,也就是说赋值符号左右两端如果类型不一致,那么只有后面这种情况。
从内存上解释为什么父类引用可以指向子类对象呢?
既然是父子关系,还是在做继承,那么还是跟内存叠加有关系。
每一个子类对象的上半截都是一个完整的父类对象部分,当父类引用指过去的时候,是能够看到完整的父类对象信息的。
没有继承关系的类,不能保证A类引用指到B类对象,能看到B类对象中有A类定义的内容,所以不允许!
子类引用指向父类对象的时候,父类对象里面没有子类特有部分,所以缺失了内容,也不允许!
从场景上解释一个对象属于子类,一定也属于它的父类。子和父是is-a关系,这是说得通的。
但是一个对象属于父类,你能保证它一定属于子类吗?
而没有继承关系的,那就更说不通的了,比如:指鹿为马。 明明是一个鹿的对象,你偏要用马的引用去指向它,肯定是不对的。你可以说它是动物、可以说它是宠物、因为鹿is-a动物;鹿 is-a 宠物;都是可行的,但鹿 is not a 马。
动态体现在哪儿?如果我们手上现在拥有一个父类引用,那么我们就不能确定这个引用到底是指向哪一个具体的对象的了。
它既可能指向自己类型的对象,也可能指向自己的各种子类对象。
而自己的某个方法,是可以被子类重写成不同的实现效果的。那么用这个引用执行重写方法,也就不能确定到底重写前还是重写后,是A子类重写后,还是其它子类重写后的效果了。只有等程序运行起来以后,根据该引用具体绑定的对象到底是谁,才能够运行出具体的效果。--- 这就是动态的体现。
转型技术赋值符号左右两端数据类型不一致,就会发生数据类型转换。
父类引用 = 子类对象 也是两端数据类型不一致,所以也属于转型技术。
基本数据类型转型技术和引用数据类型转型技术 基本数据类型转型技术1、前提:不是所有基本数据类型之间都能够进行转型,boolean不参与的;
2、自动类型转换 小类型值 赋值给 大类型的变量
强调:这里的大小 是 数据类型能表示的范围的大小,而不是空间的大小。
int num = 'A'; float f = num; double d = 100;
效果:不需要使用任何特殊语法,直接完成类型转换并且赋值成功。
3、强制类型转换 大类型的值 赋值给 小类型的变量
效果:
3-1、直接书写后,编译报错;
3-2、使用(目标类型)的强转语法,编译才能够通过;
3-3、运行的效果是有风险性的,精度有可能丢失。
引用数据类型转型技术1、前提:不是所有引用数据类型之间都能够做转型,只有有继承关系的类型之间才可以;
2、自动类型转换 子类对象 赋值给 父类引用 子类表示的范围 是小于 父类表示的范围,所以仍然是把小的数据值交给大的变量。与基本数据类型的自动转换要求是一摸一样的。
只是说它有另一个特殊的名字,又叫做“向上转型”而已。因为在继承树上,父类在上,子类在下;
效果:不需要使用任何特殊语法,直接完成类型转换并且赋值成功。
3、强制类型转换 大类型的值 赋值给 小类型的引用 又被称为"向下转型".
效果:
1、直接书写后,编译报错;
2、使用(目标类型)的强转语法,编译才能够通过;
3、运行的效果是有风险性的,风险性是运行时报错(ClassCastException),中断程序的执行。
对风险性探讨:
1、我们发现并不是每次强转都一定成功,那么情况时如何的呢?
要想强转以后,编译通过且运行也通过,只有一种情况,那就是:最终的内存结果只能是本类引用指向本类对象。
2、强转语法只是在编译期进行一个强制性的语法说明,说明什么呢?告诉编译器,我这个父类引用确实是指向的某种子类对象。
3、但是运行起来以后,如果满足你的强制说明,那么没有问题运行成功;如果不满足你的强制说明(欺骗了编译器),那么就会运行失败,报出ClassCastException。
比如:水果类 香蕉类 猪肉类 香蕉类强转水果类 可以成功 但是猪肉类和水果类不是is-a关系,所以猪肉类强转 水果类会运行失败。
强调:强转语法不是把A类对象变成B对象,只是在编译期达成的一个口头约束而已。
父类引用指向子类对象,我们能访问什么呢?
1、父类引用只能看到子类对象从父类继承而来的属性和行为,当然要受访问修饰符限制;注意:子类对象身上是有子类特有属性和行为的,只是站在父类引用的角度上看不到而已。
2、要想看到,要把引用换成子类引用,这个时候要使用强转语法,同时还必须保证运行起来以后真正给出的对象是符合强转语法的。
3、特例是在父类中定义,被子类重写的行为。由于这个行为是定义在父类中,所以父类引用能看到;而对象又是子类对象,所以执行的效果是子类重写后的效果。
练习:书写一个宠物类Pet,拥有一个叫的行为;书写Pet的两个子类Dog和Cat,分别实现叫的行为。再书写一个主人类Master,拥有一个宠物对象,主人有一个行为是喂养feed,在该方法中调用自己宠物叫的行为。最后,在main方法中测试。
instanceof在练习当中,我们看到在有的场景里面,确实会存在需要强转的情况。但是,强转又有风险度,所以,我们需要先判断类型是否匹配,这就要用到instanceof了。
instanceof是一个关键字,也是一个运算符。它是专门用来判断一个对象是否属于某个类型的,运算后的结果是boolean型结果。
语法: 对象 instanceof 类型
instanceof是专门用来规避强转带来的ClassCastException风险的,类似于非空判断专门用来解决NullPointerException风险的。
多态的应用多态参数
当我们在设计参数的时候,把参数的类型设计为父类类型,那么所有的子类对象都能够通过这个参数,传递到这个方法里面去。
这样的多态应用带来了面向对象设计中非常重要的一个原则:开闭原则。
开闭原则:Software should be opened for extension, but closed for modification。
软件对于扩展来说应该是开放的,对于修改来说应该是关闭。
也就是说好的软件设计,应该能够可以随着业务的扩展去增加新的功能,但是不应该修改已有的功能。
多态集合
int[] array = new int[10];
Object[] arrayObj = new Object[10];
可以解决数组只能存放同一数据类型元素的问题。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧