title: Java进阶学习-5 多态
date: 2020-02-02 14:36:09
tags: Java学习
子类和子类型
·类定义了类型
·子类定义了子类型
·子类的对象可以被当做父类的对象来使用
·赋值给父类的变量
·传递给需要父类对象的函数
·放进存放父类对象的容器里
子类型与赋值
子类的对象可以赋值给父类的变量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QRz1kHXP-1580663855679)(C:\Users\36987\AppData\Roaming\Typora\typora-user-images\image-20200202154747560.png)]
子类好参数传递
子类的对象可以传递给需要父类对象的函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ymkH1WTR-1580663855681)(C:\Users\36987\AppData\Roaming\Typora\typora-user-images\image-20200202154925591.png)]
子类型和容器
子类的对象可以放在父类对象的容器里
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vn4jBPGN-1580663855683)(C:\Users\36987\AppData\Roaming\Typora\typora-user-images\image-20200202155002454.png)]
调试可以发现listitem中存放的三个元素就是不同的变量。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U96q09Dw-1580663855685)(C:\Users\36987\AppData\Roaming\Typora\typora-user-images\image-20200202155733552.png)]
多态变量
Java的对象变量是多态的,它们能够保存不止一种类型的对象
他们可以保存的是声明类型(一眼就可以看出来的如Item)的对象,或者声明类型的子类的对象,Item又是CD DVD的父类 所以new的时候为CD DVD但是使用的是Item 所以Item是多态的。
当吧子类的对象赋值给父类的变量的时候就发生了向上造型
如做了CD的对象交给了父类的Item所以发生了向上造型。
向上造型
把一个类型的对象赋给另外一个类型的变量 这个过程叫做造型
子类的对象可以赋值给父类的变量
Java中不存在对象对对象的赋值
而是让这两个对象的管理者去管理同一个对象 这点不同于C++
C++是改造的不太完全的OOP语言
String s = "hello";
s = "bye";
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rmBvXIQi-1580663855687)(C:\Users\36987\AppData\Roaming\Typora\typora-user-images\image-20200202161101339.png)]
此处为s指向了一个新的对象bye 而不是将bye内容替代hello所在空间的内容 两者是相互独立的。只是管理者修改了指向的对象。java无法做这个事情。
造型cast
·子类的对象可以赋值给父类的变量
·Java中不存在对对象的赋值
·父类的对象不能赋值给子类的变量
Item item = new Item("a", 0, true, "...");
CD cd = item;
出错 子类的对象cd不能接受父类的对象item
反过来可以 父类的对象可以接收子类的对象
Item item = new Item("a", 0, true, "...");
CD cd = new CD("a", "a", 0, 0, "...");
item = cd;
可以用造型强制转化
Item item = new Item("a", 0, true, "...");
CD cd = new CD("a", "a", 0, 0, "...");
// item = cd;
// CD cc = item; //出错
CD cc = (CD)item; //可以 但运行出错 造型出错
但是容易不安全。取决于造型(在变量前面加一个括号强制转化类型)的对象。
造型
·用括号围起来的类型放在值的前面
·对象本身并没有发生任何变化
·所以不是类型转化
·运行时有机制来检查这样的转化是否合理
·ClassCastException
要区别造型和类型转化
int i = (int)10.2; //类型转化
Item item = new Item("a", 0, true, "...");
CD cc = (CD)item; //造型
类型转化10.2值不是10.2而是真的换为了int的10
造型不同 造型是吧item当做是另外一个类型来看待,而并没有改造为另外一个类型。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-78PhsgxA-1580663855689)(C:\Users\36987\AppData\Roaming\Typora\typora-user-images\image-20200202162916464.png)]
通过运行我们发现
public static void main(String[] args) {
int i = (int)10.2; //类型转化
Item item = new Item("a", 0, true, "...");
CD cd = new CD("a", "a", 0, 0, "...");
item = (Item)cd;
// CD cc = item; //出错
// CD cc = (CD)item; //可以造型 但运行出错 造型出错
Database db = new Database();
db.add(new CD("abc", "abc", 4, 60, "..."));
db.add(new CD("def", "def", 4, 60, "..."));
db.add(new DVD("xxx", "aaa", 60, "..."));
db.list();
}
item仅仅为被当做是CD类型来看待
item指向了CD的对象 这个过程称为造型。 与类型变化不同。英文名都叫cast,但是含义不同。
对于基本类型来说 cast 是类型转化
对于对象类型来说 cast 是造型。
向上造型
(1)拿一个子类的对象,当做父类的对象来用 如 item = (Item)cd;
(2)向上造型是默认的 可以不加上运算符 如item = cd;
(3)向上造型总是安全的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9PiJPwS8-1580663855691)(C:\Users\36987\AppData\Roaming\Typora\typora-user-images\image-20200202163352060.png)]
多态
函数调用的绑定
(1)当通过对象变量调用函数的时候,调用哪个函数这个事情叫做绑定
1)静态绑定:根据变量的声明类型来决定
2)动态绑定:根据变量的动态类型来决定
(2)在成员函数中调用其他成员函数也是通过this这个对象变量来调用的
for( Item item : listItem ) {
item.print();
System.out.println();
}
刚刚开始并不知道Item做指的究竟是哪个类型,只要在编译器运行的时候才知道item在运行的时候指向的是什么类型,调用什么类的print函数
所以此处是动态绑定。
java默认是动态绑定。
所有的成员函数的调用 都应该当做为动态绑定
覆盖override
·子类和父类中存在名称和参数完全相同的函数 这一对函数构成覆盖关系。
·通过父类的变量调用存在覆盖关系的函数时,会调用变量当时所管理的对象所属的类的函数。
你是一个Shape就应该会draw 就调用自己的draw自己去draw。
多态的含义:我们不需要知道具体的类型是什么 我们只要使用s.draw()
item.print() 对应类型的类就会调用其对应的函数出来 这件事情就是 多态
Object类
见下节