多态的概述
生活中: 同一个动作在不同环境下表现出来的不同状态
Java中: 同一个方法在不同的对象中体现出来不同的状态
内存中: 父类引用指向子类对象
多态的优点
1.简化了代码
2.提高了维护性和扩展性
多态的实现的必要条件:
1.存在继承关系
2.存在方法重写
3.父类引用指向子类对象
多态访问成员的特点:
成员变量: 编译时期看左边的类型,如果左边类型中没有变量,编译报错
运行时期看左边类型,左边类型的变量的值就是运行的结果
编译看左边,执行看左边
成员方法:
编译看左边,执行看右边
构造方法:
多态访问子类构造方法会先访问父类构造方法
帮助子类初始化父类继承过来的成员
静态方法:
编译看左边,执行看左边
多态的缺点: 使用父类引用无法访问子类所特有的方法
解决办法: 向下转型
基本类型存在自动类型转换和强制类型转换
引用类型存在向上转型和向下转型
向上转型(自动转换)
格式:<父类型> <引用变量名> = new <子类型>();
特点:
子类转为父类 父类的引用指向子类对象。理解为自动进行类型转换
此时通过父类引用变量调用的方法是子类覆盖或继承父类的方法
此时通过父类引用变量无法调用子类特有的属性和方法
向下转型(强制转换)
格式:<子类型> <引用变量名> = (<子类型> )<父类型的引用变量>;
特点:
父类转为子类,父类引用转为子类对象。理解为强制类型转换
在向下转型的过程中,如果没有转换为真实子类类型,会出现类型转换异常
java.lang.ClassCastException
异常名称: 类型转换异常
产生原因: 在向下转型的过程中,没有转换成真实的类型
解决办法: 在每次向下转型之前做一个类型的判断
类型判断的语法: instanceof
左边对象 instanceof 类名 这个表达式的结果是boolean类型
测试它左边的对象是否是它右边的类的实例
多态的弊端可以使用instanceof关键字+向下转型来解决
我们知道我们需要对父类的所有子类做逐一判断,违背了开闭原则
为了开闭原则我们还是可以继续开发,但是如果这个父类引用是Object呢?
无法做逐一个判断,安全隐患一致存在,后面可以考虑是泛型。
抽象类
形状类
三角形 圆形 矩形
父类的方法必须要存在,因为我们多态的必要条必须存在方法重写
方法的实现毫无意义
提供一个方法的声明即可,不需要实现,就是抽象方法
抽象类的特点:
1.抽象方法和抽象类使用 abstract 修饰
2.有一个抽象方法的类必须是抽象类
3.抽象类中一定有抽象方法吗? --> 不一定
4.没有抽象方法的抽象类有意义? --> 有意义,防止外界创建对象
防止外界实例的方式:
a.构造方法私有
b.抽象类
c.接口
4.内部类
5.抽象类不能够实例化 – 利用多态
6.抽象类的子类的特点:
a.如果子类想要继承抽象类,就必须实现抽象类中所有的抽象方法
b.如果子类不想实现父类的抽象方法,那么子类必须升级为抽象类
7.抽象类和普通类的区别
抽象类中可以有成员变量,成员方法,构造方法,静态方法,常量? 有的话又有什么意义呢?
成员变量 --> 给子类使用
成员方法 --> 给子类使用
构造方法 --> 帮助子类初始化父类继承下来的成员
静态方法 --> 直接通过类名访问,防止创建对象的不建议访问方式
常量 --> 可以,方便访问
抽象类和普通类没有区别,只不过是抽象类多了抽象方法而已
抽象类的抽象方法强制子类重写
非抽象方法直接给子类使用
构造方法和成员变量直接给子类使用
抽象类是一个彻头彻尾的服务类,服务于所有的子类
8.抽象类的成员一般使用 public 或者 protected
9.private final static native 可以用来修饰抽象方法吗?
private修饰的方法不能够被子类继承,更不可能被重写,abstract修饰的方法强制子类重写,二者冲突
final修饰的方法不能够被子类继承,更不可能被重写,abstract修饰的方法强制子类重写,二者冲突
static修饰的方法一般方便调用,一般都是用来实现功能的,抽象方法没有方法体,二者没有意义
native修饰的方法不是Java实现的,有方法体,抽象方法没有方法体,二者没有意义
接口
1.接口是一种标准,是一种规范,是一种约定
2.接口可以扩展功能
3.接口是灵活的,可以即插即拔
4.接口由继承者来实现
接口的概念:
从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和抽象方法的定义,而没有变量和方法的实现。
接口的格式:
格式
public interface 接口名{
//常量
//抽象方法
}
接口的实现类格式:
public 类名 implements 接口{
// 实现接口的方法
//普通方法
}
接口的特点:
1.接口使用interface修饰
2.接口是常量和抽象方法的集合
常量: 默认使用 public static final
方法: 默认使用 public abstract修饰
3.在JDK1.8以后不仅仅只有常量和抽象方法,还有默认方法和静态方法
默认方法用来直接给子类使用,如果子类想重写也可以自行根据需求重写,不会强制重写
静态方法用来直接通过接口名访问
4.接口不能够实例化
5.接口如果想要实例化–利用多态
6.接口的实现类特点:
a.如果一个类想要实现一个接口就必须实现接口中定义的所有抽象方法
b.如果一个类不想实现接口中的抽象方法,那么实现类也升级为接口
7.接口是一种规范
8.接口可以用来扩展功能
9.接口是灵活的
10.接口是由继承者来实现
11.接口/类之间的关系
类和类 单继承 不可以实现
类和接口 不可以继承 多实现
接口和接口 多继承 不可以实现
12.接口和继承的区别?
什么时候使用接口? 什么时候使用继承?
大部分情况下使用接口,因为接口灵活,主要是降低了耦合性,并且接口是一种规范
继承主要体现在代码的抽取以及多态的必要条件
思想:
1.开闭原则
2.高内聚,低耦合
3.面向接口编程