java多态如何实现
不会吧不会吧,还有人不懂java多态? 今天我温习面试题,多态是个什么只记得可以用父类接收充当返回值了,哎,这里回顾记录一下
多态的概念
面向对象三大特性之一,用来解决程序的扩展性问题,可以简单理解为一种事物的多种表现形式,比如:
一个学生既是学生,同时也是个人类,那我们聊天的时候,会说他是个人类吗?不会我们通常说他是个学生。(说人类的不觉得很奇怪吗)
大家先搞懂几个名词,接下来才会明白我说的专业术语
比如我们创建一个实体类A 、一个实体类B,以B继承A,这个时候,你创建新对象的时候有两种方式定义返回值:
1 | A a = new A(); //基类就是A类 |
我们定义的参数名(上面的小a 小b)就是引用变量,好了,现在我们知道了基类是什么,引用变量是什么。
先总结出个特点:
- 代码体现就是 父类引用变量可以指向子类
- 达成这个效果的前提条件是,子类继承了父类,或者实现了父类
- 调用父类的引用方法会调用子类改写后的方法(这也是我们继承了别的方法之后,重写了却调用我们写的方法而不是人家父类原本方法的原因)
多态例子
A类
1 | package com.czxy.duotai; |
B类
1 | package com.czxy.duotai; |
测试类:
1 | package com.czxy.duotai; |
我们这个时候在测试类中运行会发生什么?猜一猜
解释:
先执行了一个 B类中的c方法,然后B类中的b方法,然后B类中的c方法
可是我们只执行了一次b方法,一次c方法啊,这是因为,在执行程序的时候,先执行了父类A的构造方法,但是A调用的构造方法中的方法看起来是A自己的,实际上因为绑定的是引用变量指向的具体实例对象的方法,也就是内存中正在运行的那个对象的方法,而不是引用变量的类型中定义的方法,也就是说,会调用子类的方法。
所以,我们的结果第一条打印的是B类的方法的原因是 A类的构造方法调用了内存中实例对象的A的子类同名方法 b。
有人可能不清楚为什么我创建的基类是B类,实例对象也是B类,为何还会调用到A的构造函数? 这就是另一个问题了,构造函数的执行顺序,这里不讲
多态扩展
测试类:
1 | package com.czxy.duotai; |
我们这个时候在测试类中运行会发生什么?你再猜一猜
其实,多态本身是子类类型向父类类型向上转型的过程, 这是默认转型模式,隐藏了子类类型,提高了代码的扩展性,你也可以将父类强转为子类作为基类来接收:
1 | B a = (B) (new A()); |
但是这有个缺点,将方法强转为B为基类接收,就会使我们只能调用B的方法了,而无法调用A的其他继承类的方法了,而且我们有些方法自带一些特殊方法,也无法调用了
举个例子:
新增扩展Cat类:
cat类中有自己新增的方法,我们如何调用(你继承了A是不假,但是并不是只能调用C与A都有的方法,而是实现了谁就调用谁的方法,只不过多态提供了你可以调用默认父类方法,和你用父类方法不爽还可以自己重写的选择)
我cat 只会 叫 喵喵喵喵喵
1 | package com.czxy.duotai; |
新增扩展Dog类
我dog只会叫 汪汪
1 | package com.czxy.duotai; |
升级父类
1 | package com.czxy.duotai; |
疑问
程序动态调用的时候如何确定调用猫是猫叫,狗是狗叫?
测试类:
1 | package com.czxy.duotai; |
好了,这样便实现了是狗类掉狗叫,猫类掉猫叫
我们用实体类的继承关系就实现了java 接口的作用!!!!!(没错,这其实就是人家接口的工作)