多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:
![image-20220826154158592](https://i-blog.csdnimg.cn/blog_migrate/e543e1ef361daa5749fa8cd711361ab1.png)
1.1多态的优点
- 消除类型之间的耦合关系
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
1.2多态存在的三个必要条件
- 继承
- 重写
- 父类引用指向子类对象
1.3多态的实现方式
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。
下面我们通过一个代码示例,通过丰富的注释和解析,深入理解Java多态:
package com.fang.wordcount_1;
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
/**
* 上面两行可以发现,show方法要求传入的是动物对象,因为猫和狗都继承了动物类,因此符合规范,
* 同时体现出多态的优势:一个形参可以对应多个实参,同时这也是一个重写式多态
*/
Animal a = new Cat(); // 向上转型:通过子类实例化父类
a.eat(); // 调用的是 Cat 的 eat
//a.work();如果运行这一行就会发现,无法调用work方法,因为动物类只有eat一个方法,从而cat失去了特有方法
Cat c = (Cat)a; // 向下转型:通过父类强制转化为子类
c.work(); // 调用的是 Cat 的 work
/**
* 上面两行体现了向下转型的用处,我们可以知道,对象a目前是一个动物对象,不能执行猫或者狗的特有方法
* 但是,如果通过向下转型,将动物a对象,转化为一个猫c对象,这样就可以调用猫的特有方法了
*/
/**
* 得出结论:
* 向上转型 : 通过子类对象(小范围)实例化父类对象(大范围),这种属于自动转换
* 向下转型 : 通过父类对象(大范围)实例化子类对象(小范围),这种属于强制转换
*/
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat)a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
}
//定义一个抽象类
abstract class Animal {
abstract void eat();
}
//下面的每一个类继承抽象类,重写接口中的方法
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}
如果你能理解整个代码的核心内容,那么你已经掌握了多态!
对于多态我的理解是:同一个行为具有多个不同表现形式或形态的能力就是多态
1.3补充说明
多态一般分为两种:重写式多态和重载式多态。
重载式多态,也叫编译时多态。也就是说这种多态再编译时已经确定好了。重载大家都知道,方法名相同而参数列表不同的一组方法就是重载。在调用这种重载的方法时,通过传入不同的参数最后得到不同的结果。
但是这里是有歧义的,有的人觉得不应该把重载也算作多态。因为很多人对多态的理解是:程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,这种情况叫做多态。 这个定义中描述的就是我们的第二种多态—重写式多态。
重写式多态,也叫运行时多态。这种多态通过动态绑定(dynamic binding)技术来实现,是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。也就是说,只有程序运行起来,你才知道调用的是哪个子类的方法。 这种多态通过函数的重写以及向上转型来实现,我们上面代码中的例子就是一个完整的重写式多态。我们接下来讲的所有多态都是重写式多态,因为它才是面向对象编程中真正的多态。
总而言之我的理解:重载式多态,在编码等过程中,并没有很好的体现出多态的优势,但是不得否认也是多态的一种编写方式,而给出的重写式多态案例中,相比于重载式多态,在编码思路和代码量以及聚合度方面都较好的体现出了多态的优势,