版权声明
- 本文原创作者:清风不渡
- 博客地址:https://blog.csdn.net/WXKKang
一、引言
这一篇主要记录面向对象的第三个特征——多态,那么什么是多态呢?从字面意思上理解,多台——即多种形态、多种状态,那么我们怎么去实现多种状态呢?它的作用又是什么呢?我们为什么要使用多态呢?
我们都知道,封装和继承是为了提高代码的重用性,而对于多态,我自己理解的是为了让代码更加的灵活,简单来说就是用父类或接口的引用变量指向子类的对象,有了这个意识之后,我们在来看看怎样去实现它吧
二、多态
1、多态实现的条件
既然是通过父类或接口的引用变量指向子类的对象,那么实现多态的必要条件就是:继承、重写
多态实现的基础:父类声明的变量可以引用所有子类的对象,并且我们只有在运行的时候才会知道引用变量所指向的具体实例对象
2、多态的作用
把不同的子类都当做父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化
简单的来说就是用父类或接口的引用变量指向子类的对象
解释: 我们怎样去理解上面这段话呢,通俗的来讲就是我们可以通过声明一个父类的对象,然后通过这个对象来指向(new出)子类的对象,这样的话,这个对象就具备了子类所拥有的属性和方法,例如下面这样,学生类继承了人类,我们可以像下面这样写来实现多态:
People p1 = new Student();
现在这个p1就具备了学生类中的属性与方法,假如学生类重写了父类(人类)的某一个方法,那么p1包含的对应的方法就是重写后的方法
如果还有一个类叫教师类也继承了人类,我们的另外一个类中有两个方法,它们分别需要学生类和教师类的实例对象,那么我们只需要声明一个全局变量,类型为People,然后在具体的方法中通过这个变量指向具体的学生类或者教师类即可,下面我们通过一个简单的例子来理解它们吧:
父类(人类):
package cn.com;
public class People {
//people类构造函数
public People() {
super();
}
//父类的play方法
public void play() {
System.out.println("人们可以玩很多好玩的");
}
}
子类(学生类):
package cn.com;
public class Student extends People{
//无参构造函数
public Student() {
super();
}
//重写父类play方法
@Override
public void play() {
System.out.println("学生不能玩呀,要加班写作业嘞");
}
}
测试类:
package cn.com;
public class Demo {
public static void main(String[] args) {
//普通的实例化父类
People people = new People();
System.out.println("---普通的实例化父类的play方法------");
people.play();
//普通的实例化子类
Student student = new Student();
System.out.println("---普通的实例化子类的play方法------");
student.play();
//父类引用指向子类对象
People p1 = new Student();
System.out.println("---父类引用指向子类对象的play方法----");
p1.play();
}
}
运行结果:
通过上面的示例我们可以看到,普通实例化子类和父类引用子类对象所产生的效果是一样的,这样在我们需要实例化多个对象的时候,如果这些类都继承了同一个类,那么我们就可以使用多态了
类型转换的重点:
1、弄清楚继承关系、谁是父类谁是子类
2、关键点在于创建对象时调用的是谁的构造函数
三、多态的实现
1、基于继承的实现的多态
多个子类对同一个父类方法的重写,可以在运行时表现出不同的行为,这个我们在上面的示例中已经看到了,故在此不做过多赘述
2、基于接口的实现的多态
一个接口有多个实现类。所以,多个实现类对接口中同一方法的重写,也可以在运行时表现出不同的行为,实现方法和上面的例子相同
注意:命名规范:接口名——>接口名Impl
3、函数参数的多态
同样,多态也可以运用在函数的参数中,多态可以作为形参,接收范围更广的对象,使得接收的参数更加灵活
比如说我们可以将父类作为形参,在调用这个方法时传入的参数既可以是这个类的对象,也可以是它的子类的对象,这样就使得一个方法接收的参数更加的灵活、广泛
3、函数返回值的多态
多态同样可以作为返回值,接受范围更广的对象,即我们可以将父类设置为返回值类型,这样我们不但可以将父类对象作为返回值传出,也可以将子类对象作为返回值传出,例如:
public 父类类名 方法名(){
return 父类对象;
}
public 父类类名 方法名(){
return 子类对象;
}
好啦,这个就是Java的第三大特征,封装了,学习完这些是不是觉得多态是为了让代码更加灵活呢?我们下一篇再见吧