今天,我们来学习面向对象的最后一个特性——多态(Polymorphism)
多态
多态的定义
多态:同一个人(对象)在不同的环境下可以转换为不同的身份(状态)
那么我们为什么要使用多态呢?其实是为了实现面向对象的开闭原则
举个例子,假设我们现在要给宠物喂食
1.要编写狗狗类,增加狗狗吃食的方法
2.要编写企鹅类,增加企鹅吃食的方法
3.创建主人类,编写喂狗狗吃食的方法、编写喂企鹅吃食的方法
4.编写测试类,调用主人类给狗狗喂食的方法、调用主人类给企鹅喂食的方法
那么我们要想一下?如果新添加了一个宠物怎么办?
如果新添加了100个怎么办?每一个主人类都要添加一个喂食的方法么?
显而易见,这不现实,多态就是为了解决这一问题
多态即同一种操作,由于条件不同,产生的结果也不同
对于同一个引用类型,使用不同的实例而执行不同的操作
使用多态
在使用多态时,必须要满足三个条件
- 拥有继承关系
public class Animal {
public void eat() {
}
}
- 子类重写父类的方法
public class Dog extends Animal {
@Override
public void eat() {
}
}
- 父类/接口引用指向子类/实现类对象
Animal animal = new Dog() ;
实现多态的两种方式
- 使用父类作为方法形参实现多态
- 使用父类作为方法返回值实现多态
向上转型
在继承性关系中,将子类向父类转换,即为向上转型。但是必须要满足多态的条件,才能转型
public void eat(Food food) {
}
public class Fish extends Food {
public Food getFood() {
return new Fish() ; //向上转型
}
}
// 调用过程
eat(fish) ;
注:父类引用无法调用子类特有方法(此时就需要向下转型)
向下转型
强制类型转换(拥有父子关系才能转换)。将一个父类转换成子类对象的过程
动态绑定:运行时才知道彼此之间的关系
、
instanceif关键字
当子类中存在父类中没有的功能或方法时,将父类向下转型,转换成子类类型才能调用子类中的特有方法,此时转换前一定要进行instanceof判断,你只要通过判断知道是否是该子类类型才能进行转换,如果随意转换就会报ClassCastException类转换异常
接口
接口的定义
接口是一种能力,同时也是一种约定,定义了一种标准,表示某一种功能特性方法的集合。接口使用interface关键字声明,使用implements关键字实现。一个类可以同时使用实现多个 接口,如果不同的接口被实现相同的方法定义,只会在实现类中实现一次。interface可以使用public、default。接口是一种特殊的抽象类。非抽象类实现接口时必须实现接口中的全部方法
public interface Myinterface{
public void foo();
//所有方法都是public abstract,属性都是静态常量
//在java8的新特性中,新增了默认方法,即default void foo()
//不过在反编译文件中,该方法依旧是声明方法,其里面具体的内容是程序计数器,并没有执行方法中的内容
}
接口的特性
- 接口不可以被实例化
- 实现类必须实现接口的所有方法
- 实现类可以实现多个接口
- 接口中的变量都是静态常量
面相接口编程
接口是一种能力,面向接口编程体现在接口的方法上。之前所有学习过的编程模式都是面向与类编程,面相接口编程会面向于行为方法
程序设计时关心实现其有何能力,而不关心实现细节;关心面向接口的约定而不考虑接口的具体实现
面试题
如何理解接口是一种能力?
接口比抽象类有更好的特性:
- 可以被多继承
- 设计和实现完全分离
- 更自然的使用多态
- 更容易搭建程序框架
- 更容易更换实现
接口与抽象类的区别
语法层面上的区别:
- 抽象类可以提供成员方法上的实现细节,而接口中只能存在public abstract方法;
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的
- 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口
设计层面上的区别:
- 抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为、但是接口却是对类局部(行为)进行抽象
- 设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计
以上便是本篇文章的所有内容,如有疑问还请各位评论区多多提出!!!