目录
- 多态(条件:继承、重写、父类引用指向子类对象)
- 类
- 抽象类
- 接口
一、多态
- 什么是多态
- 多态的优点
- 多态的三大条件
- 重写和重载与多态的关系
1 - 什么是多态
多态的定义:
(1)多态就是同一个行为具有多个不同表现形式或形态的能。
(2)多态就是同一个接口,使用不同的实例而执行不同的操作。如下图:
(多态性是对象多种表现形式的体现)
2 - 多态的优先
- 消除类型之间的耦合关系
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
3 - 多态的三大条件
- 继承
- 重写
- 父类引用指向子类对象
<例子>
class A{
int num=0;
public void method(){
System.out.println("我是父类方法")
}
}
//【1】继承了普通类
class B extends A{
int num=1;
//【2】重写父类方法 @Override标记用于检测某方法是不是重写方法
@Override
public void method(){
System.out.println("我是子类,我重写了父类方法")
}
}
public class test{
public static void main(String[] args){
//【3】创建对象 父类引用指向子类对象
A a=new B();
//调用方法
a.method();//此处调用的是子类的方法,因为创建的是子类对象 且该方法覆盖重写了父类的方法
System.out.println(a.num);//此处输出的是0,因为变量不可以被覆盖重写,所以直接使用的是父类的变量 (编译期看等号左边,运行期看等号右边)
}
}
结果
我是子类,我重写了父类方法
0
下面一张图是多态不完全的内存图,仅参考,帮助理解
4- 重写和重载与多态的关系
(1)重写(Override):重写是子类对父类的–允许访问的实现过程(即方法)进行重写编写,返回值和形成都不能变。重写是多态实现的体现(外壳不变,核心重写)。
(注意1: 在高Java版本中,返回值可修改。条件是:子类的返回值类型级别小于父类的返回类型级别。方法权限也可以修改,要求是:子类权限高于父类权限。)
(注意2: 重写方法不能抛出新的检查异常或者比被重写方法声明更加宽泛的异常。例如父类声明一个检查异常IOException,但是在重写这个方法的时候,不能抛出Exception异常,因为Exception是IOException的父类,只能抛出IOException或者其子类)
重写规则
1、参数列表与被重写方法的参数列表必须完全相同。
2、重写方法返回类型与被重写方法的返回类型可以不相同,但必须是父类返回类型的派生类。(java5<要要求必须一致,java7开始可以不一样)
3、重写方法访问权限不能比父类中重写的方法的访问权限低。
4、父类的成员方法只能被它的子类重写
5、声明为final的方法不能被重写
6、声明为static的方法不能被重写,但是能够再次声明。
7、子类和父类在同一个包中,那么子类可以重写父类所有的方法,除了声明为private和final的方法
8、子类和父类在不同包中,那么子类只能够重写父类声明为public和protected的非final的方法。
9、重写方法能够抛出任何非强制异常。(异常分为:强制性异常(CheckedException)和非强制性异常(UncheckedException)。强制性异常:所谓强制性异常就是在编写程序的过程中必需在抛出异常的部分try catch 或者向上throws异常。)。
10、构造方法不能被重写
11、如果不能继承一个方法,就不能重写这方法。
<例子>
//父类
Class A{
public void method(){
System.out.println("这是A");
}
}
//子类继承
Class B extends A{
@Override//方法重写 实现多态
public void method(){
System.out.println("这是从写了A方法的B");
}
}
public class test{
public static void main(String[] args)
{
//实现多态 父类引用指向子类对象
A a=new B();
a.method();
}
}
结果
这是从写了A方法的B
(2)重载(Overload):重载是一个类里面,方法名字相同,而参数不同数据类型或参数个数不同。返回类型可以相同也可以不相同。
(注意1: 每个重载的方法(或构造函数)都必须有一个独一无二的参数类型列表。最常用的就是构造器的重载。)
重写规则
1、被重载的方法必须改变参数列表(参数个数或参数类型)
2、被重载的方法可以改变返回类型
3、被重载的方法可以修改访问修饰符
4、被重载的方法可以声明新的或更加广的检查异常
5、方法能够在同一个类中或子类中重载
6、无法以返回值类型作为重载函数的区分。
<例子>
Class A{
public void fun(){
System.out.println("方法参数个数:0个");
}
//重载方法fun
public void fun(int a){
System.out.println("方法参数个数:1个");
System.out.println("参数数据:"+a);
}
//重载方法fun
public void fun(double a){
System.out.println("方法参数个数:1个");
System.out.println("参数数据:"+a);
}
//重载方法fun
public void fun(int a,int b){
System.out.println("方法参数个数:1个");
System.out.println("参数数据:"+a
+l+" "+b);
}
}
小结重载与重写
区别点 | 重载方法 | 重写方法 |
---|---|---|
参数列表 | 必须修改 | 一定不能修改 |
返回类型 | 可以修改 | 一定不能修改(高版本Java中可以修改,但不限是低于当前返回类型级别) |
异常 | 可以修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
访问 | 可以修改 | 一定不能做更严格的限制(子类权限需大于等于父类) |
重载是不是多态的表现,下面是个人理解
1、根据多态的简单定义(同一个方法具有多个不同的表现),可以认为重载是多态的体现(我称之为“伪多态”)。
2、根据多态的要求(继承、重写、父类引用指向子类对象)说明,可以很肯定的认为重载不是多态的体现。
3、最后结论,狭义地(更严格地)说重载不是多态;广义地(更简单地)说重载是多态,我称这种多态为“伪多态”。
二、类
- 什么是类
- 类的格式
- 类的注意事项
1- 什么是类
类定义:类是一个模板,他描述了一类对象的行为和状态。类有数据成员变量(状态)和成员方法(行为)。
2- 类的格式
声明类的格式:
[public] class 类名 [ extends 父类名] [implements 接口名] { [成员变量];[成员方法]}
public class A{
//成员方法
//成员变量
}
3- 类的注意事项
1、类是单继承(extends)类的,但可以多继承类
2、类可以多实现(implements)接口。
3、类能继承私有(private)成员,但无法被子类直接访问,可以间接访问(在同一个类中,通过另外一个方法访问,访问该类的私有成员)
三、抽象类
- 什么是抽象类
- 抽象类的格式
- 抽象类的注意事项
1 - 什么是抽象类
抽象类定义:所有的对象都是通过类来描述的,但反过来,并不是所有的类都是用来描述对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类,用关键字abstract声明。
2 - 抽象类的格式
[public等] abstract class 类名{ [ 成员变量 ] [成员方法] [ 抽象成员方法 ] }
public abstract class A{
//成员变量
//成员方法
//抽象成员方法
}
3 - 抽象类的注意事项
1、抽象类除了不能实例化(new)对象之外,类的其他功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
2、由于抽象类不能实例化对象,所以抽象类必须被继承,才能使用,同时其所有抽象方法在子类中都要被实现。通常在设计阶段决定要不要设计抽象类。
3、抽象类不一定有抽象方法,但是有抽象方法的类一定是抽象类。
4、子类必须实现父类的所有抽象方法,否则声明自身也为抽象类。
5、抽象类中的抽象方法用abstract声明,并且抽象方法只声明不定义。
6、构造方法、类方法(static修饰的方法)不能声明为抽象方法。
7、abstract关键字和final关键不能同时出现。因为一个是声明的成员需要在子类中修改,另外一个是声明的成员在任何地方都不能被修改的。
四、接口
- 什么是接口
- 接口的格式
- 接口的注意事项
1- 什么是接口
接口定义:接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征,没有方法的实现。接口需要被实现(implements)才能实现接口所具有不同的行为(功能)。
2- 接口的格式
[ 可见度(public等)] interface 接口名称 [ extends 其他接口的名称]{
[抽象方法]
[public] [abstract] 返回数据类型 方法名(参数列表);
[声明常量]
格式:[public static final] 返回数据类型 成员变量名=数据值
[默认方法](高版本Java)
[public] default 返回类型 方法名(参数列表){方法体}
[静态方法](高版本Java)
[public] static 返回数据类型 方法名(参数列表){方法体}
[私有方法](高版本Java)
private 返回值类型 方法名(参数列表){方法体}
[静态私有方法](高版本Java)
private static 返回值类型 方法名(参数列表){方法体}
}
3- 接口的注意事项
1、抽象类中的方法可以有方法体,就是能实现方法的具体功能。但接口中的方法不行(高版本java中的默认、静态、私有方法可以有方法体)。
2、抽象类中的成员变量可以是各种数据类型的,人接口中的成员变量只能是public static finale类型的,通过接口名引用。
3、接口中不能含有静态代码块,如static{代码块}
。接口中,不能含有静态方法,高版本Java中可以有静态方法。而抽象类中,无论什么时候都可以有静态静态代码块和静态方法。
4、一个类只能继承(extends)一个抽象类,而一个类可以有实现(implements)多个接口。
5、接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
6、接口中每一个方法也是隐式抽象的,声明时同样不必须写abstract关键字
7、接口中的方法在低版本Java中都是公有的,高版本中,可以有私有。
8、一个接口可以继承(extends)另外一个接口。
9、类在实现接口方法时,不能抛出强制性异常,只能在接口中或者继承接口的抽象类中抛出该强制性异常。
补充
强制性异常和非强制性异常,即是检查性异常和非检查性异常。
总结
多态可以通过类的继承(extends)类和抽象类和实现(implements)接口,并重写父类的方法进行多态体现。