浅谈面向对象中的多态
面向对象有三大特征:封装、继承和多态。今天我们来谈谈多态。
多态
多态概述
什么是多态?
每每谈及多态时,总有一种只可意会不可言传的感觉。简单来说多态就是某个事物,在不同时刻表现出来的不同状态。
比如:猫可以是猫的类型,也可以是动物的类型(因为猫也是动物)。
多态的前提
- 类和类要有继承关系。
- 要有方法重写。没有也行,但没有的话多态就没有意义了。
- 要有父类引用指向子类对象。(父类 对象名 = new 子类();)
多态中的成员的访问特点
- 成员变量的访问特点:编译看左边,运行看左边
- 成员方法的访问特点:编译看左边,运行看右边
- 构造方法:创建子类对象时,会先访问父类的构造方法,对父类的数据进行初始化
- 静态方法的访问特点:编译看左边,运行看左边(静态方法是属于类的,算不上重写,所以访问还是左边的)
多态的好处
可总结如下
- 提高了代码的维护性(继承)
- 提高了代码的扩展性(多态)
多态虽然有好处,但是也有弊端。多态的弊端就是不能够访问子类特有的功能。(因为是父类引用指向子类对象)
在多态的方式下,若要访问子类特有的功能则需要向下转型,即把父类的引用强制类型转换为子类的引用。
那么有向下转型,就有向上转型,多态就是典型的向上转型,父类引用指向子类对象。
抽象类
抽象类概述
在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。
抽象方法的格式:
修饰符 abstract 返回值类型 方法名();
抽象类的格式:
abstract class 类名{
}
那么抽象类有哪些特点呢?
- 抽象类和抽象方法必须用abstract关键字修饰。
抽象类格式:abstract class 类名 {
}
抽象方法格式:public abstract void eat(); - 抽象类不一定有抽象方法,但有抽象方法的类一定是抽象类
- 抽象类中可以有构造方法,但抽象类不能进行实例化。抽象类中的构造方法是用于子类访问父类数据时的初始化
- 抽象类虽然不能直接初始化,但可以间接初始化。按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
- 抽象类的子类:要么也是抽象类;要么重写抽象类中的所有抽象方法
抽象类的成员特点:
- 成员变量:既可以是变量,也可以是常量。
- 构造方法:有构造方法。用于子类访问父类数据的初始化。
- 成员方法:既可以是抽象的,也可以是非抽象的。
抽象类的成员方法特性:
- 抽象方法:强制要求子类做的事情。子类必须重写父类的抽象方法。
- 非抽象方法:子类继承的事情,提高代码复用性。
一个类如果没有抽象方法,可以定义为抽象类,但是不能创建对象。
接口
何为接口?
为了体现事物功能的扩展性,Java中提供了接口来定义一些额外功能(这些额外功能并不是类的对象所共有的,只是一部分对象拥有),并不给出具体实现,当有事物向具备这些额外功能时,就可以实现这个接口
接口的特点
- 接口用关键字interface表示
接口的格式为:
interface 接口名 {
}
- 类实现接口用implements表示
格式为:
class 类名 implements 接口名 {
}
这个类,可以叫做接口的子类, 这个接口 可以叫做这个类的父接口。
- 接口不能实例化
若要实例化,则需要用多态的方式进行实例化 - 接口的子类:可以是抽象类(但是意义不大);可以是具体类,要重写接口中的所有抽象方法(推荐这样写)
作为接口的子类,有什么要求?
- 要求子类必须重写接口中所有的抽象方法
- 如果不想重写,那么这个类可以为一个抽象类,将接口中的抽象方法继承即可
接口成员特点
- 成员变量:只能是常量,并且是静态的。默认修饰符:public static final,但是建议我们在写的时候手动给出。
- 构造方法:接口没有构造方法。
- 成员方法:只能是抽象方法。默认修饰符:public abstract,但是建议我们在写的时候手动给出。
类、接口之间的关系:
- 类与类:继承关系,只能单继承,可以多层继承。
- 类与接口:实现关系,可以单实现,也可以多实现。也可以在继承一个类的同时实现多个接口。
- 接口与接口:继承关系,可以单继承,也可以多继承。
抽象类和接口的区别:
成员的区别
- 成员变量:
抽象类中的成员变量既可以是常量,也可以是变量;
接口中的成员变量只能是静态的常量 - 成员方法:
抽象类中的成员方法既可以是抽象的,也可以是非抽象的;
接口中的成员方法必须是抽象的 - 构造方法:
抽象类中有构造方法;
接口中没有构造方法
关系的区别:
- 类与类:继承关系,单继承
- 类与接口:实现关系,单实现和多实现均可
- 接口与接口:继承关系,单继承和多继承均可
设计理念的区别:
- 抽象类:被继承 体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
- 接口:被实现 体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。
JDK1.8之后在接口中提供了用default修饰的方法,可以给出功能的具体实现,子类可以继承下去用
abstract关键字
abstract关键字:抽象的,可以修饰类,也可以修饰方法。
特点:
- abstract 修饰类,此类就不能直接实例化
- abstract 修饰方法,修饰的方法,要求子类必须重写
abstract和以下关键字不共存:
-
private
原因:private修饰的成员不能被子类继承,而abstract要求继承成员,并重写方法。 -
final
冲突的原因同上。 -
static
不能共存 无意义