为了方便理解,鄙人觉得回答了下面这几个问题,这玩意大概就理解了:
1.多态是个什么鬼?
2.为啥需要多态?多态的优势在哪?劣势在哪?
3.如果需要,那么它是怎么实现的,原理是什么
4.如何使用和使用场景是什么?
下面开始回答上面的问题,额,好吧,这个是我百度了好多地方然后结合自己理解搞的,不过基本就是这个意思
先从1搞起:
官方是说:
- 接口的多种不同的实现方式即为多态。
- 多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术。
- 我们在程序中定义的引用变量所指向的具体类型和通过该引用变量的方法调用在编程的时候并不确定,当处于运行期间才确定。就是这个引用变量究竟指向哪一个实例对象,在编译期间是不确定的,只有运行期才能确定,这样不用修改源码就可以把变量绑定到不同的类实例上,让程序拥有了多个运行状态,这就是多态。
很懵圈,对不,额,不懵圈就直接去看2吧,下面是懵圈的人看的:
父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,然后你编译的时候不知道这个指针指向哪里,等到运行时才知道,从而去指向对应的子类或者接口具体实现的类所指向的方法,额,还是懵圈,对不,就举个生活中的例子,就比如,你家有亲戚结婚了,然后你家要派个人过去吧,邀请函是叫你爸过去,但是你爸偷懒不想过去,于是你爸就想到了个方法,把这个邀请函给你或者你其他兄弟姐妹或者给他老婆,就你妈,这个你爸给你邀请函的过程,就是多态,就是这个邀请函首先代表人是你老爸,然后跟你老爸最亲的人,就是他的儿子女儿老婆,这些人都是可以去的,这个就是多态,就你去的人不确定,又可能是你老爸自己去,也有可能是他儿子或者女儿去,真想知道是谁去的话,就得到时候在亲戚上面看到才知道
好了,现在来回答2:
多态的优点:
(1)可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
(2)可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
(3)接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
(4)灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
(5)简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。
劣势就是使用了多态后不能使用子类的方法了,也很好解决,可以用向下转型的方法来解决,比如
public class A {
public void show() {
System.out.println("A:show");
}
}
public class B extends A{
public void show() {
System.out.println("B:show");
}
public void show2() {
System.out.println("B:show2");
}
}
A c=new B();
c.show();这就是多态的,额,我也不知道叫啥,反正就是不用接口的时候的调用,其中c在运行时指向了A的子类B,所以输出的是B中show的方法,那么你想继续输出B的其他方法,比如show2(),额。你会发现c.show2()会报错,编译时会报找不到这个方法的错误,这个就是劣势了,怎么解决呢,可以直接强转成B类,就比如B b=(B)c;这样就能调用子类B的方法了
现在回答3,java中多态的实现原理:
简单版本:
原理也很简单,父类或者接口定义的引用变量可以指向子类或者具体实现类的实例对象,由于程序调用方法是在运行期才动态绑定的,那么引用变量所指向的具体实例对象在运行期才确定。所以这个对象的方法是运行期正在内存运行的这个对象的方法而不是引用变量的类型中定义的方法。
术语版本:
我们将引入Java静态分派和动态分派这个概念。
- 静态分派:所有依赖静态类型来定位方法执行版本的分派动作。静态分派发生在编译阶段,因此确定静态分派的动作实际上不是由虚拟机来执行的,而是由编译器来完成。(编译时多态)
- 动态分派:在运行期根据实际类型确定方法执行版本的分派动作。(运行时多态)
如果想深入的同学可以参考可以参考《深入理解Java虚拟机》。
参考:
https://blog.csdn.net/sunxianghuang/article/details/52280002
https://www.jianshu.com/p/68ddb5484ca2
4:
//接口方式的多态
public interface ITest {
void test();
}
public class KeyBorad implements ITest{
@Override
public void test() {
// TODO Auto-generated method stub
System.out.println("我是键盘");
}
}
public class Mouse implements ITest{
@Override
public void test() {
// TODO Auto-generated method stub
System.out.println("我是鼠标");
}
}
public class MotherBorad {
public void show(ITest a) {
a.test();
}
}
MotherBorad a=new MotherBorad();//创建管理类
KeyBorad keyborad=new KeyBorad();
ITest test=new KeyBorad();
a.show(test);
//普通类方式的多态,引用2的代码
A c=new B();
c.show();
主要接口多态这种要掌握,确实用多了对代码解耦性特别好