面向对象(三)——继承和多态
继承性
目的
提高代码复用性
语法
class 子类名 extends 父类名{子类相关逻辑代码}
- 子类会自动拥有父类定义的属性和方法,不用管修饰词是什么
- 父类叫超类或基类
- 子类叫派生类
Java继承性特点
1、Java中只支持单继承,不支持多继承。也就是一个子类只能有一个直接父类,但是一个父类可以有多个子类。具体关系如下图。
2、子类继承父类之后,就可以获取直接父类以及间接父类的相关方法和属性了。
3、当我们没有显示的声明一个类的父类的时候,该类将继承自java.lang.Object类。
4、其实我们定义的所有类都直接或者间接继承自java.lang.Object类,所以可以说我们定义的所有类都有父类,也就意味着所有定义的Java类都可以使用java.lang.Object类声明的功能。
5、Java所有类都是Object的子类
6、super()和this()不可以同时在一个构造器出现
继承的本质分析
- 看子类是否有该属性,有并且可访问,则返回信息
- 否则,看父类,同理,有并且可访问,则返回信息
- 否则,看更上一级,知道Object类
方法重写(override)
- 正常情况下我们的子类在继承父类的时候会继承父类所有的方法,但是有时候子类对相关的方法有不同的实现要求,这个时候就需要我们在子类中重写父类相关的方法,用以覆盖父类的方法。在这时如果创建子类的对象并调用相关方法,实际执行的是子类重写后的方法。
- 重写方法的规定
- 子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同
- 子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符,特别的子类不能重写父类中声明为private权限的方法。
- 针对返回值
- 父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
- 父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
- 父类被重写的方法的返回值类型是基本数据类型,则子类重写的方法的返回值类型必须是相同的基本数据类型
- 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
- 注意事项:静态方法无法被重写。
子类实例化的全过程
- 从结果看:子类继承父类以后,就获取了父类中声明的属性或方法。
创建子类的对象,在堆空间中,就会加载所有父类中声明的属性。 - 从过程看:当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的父类的构造器直到调用了java.lang.object类中空参的构造器为止。正因为加载过所有的父类的结构,所以才可以看到内存中有父类中的结构,子类对象才可以考虑进行调用。
继承性的好处
1、减少了代码的冗余,提高了代码的复用性
2、便于功能的扩展
3、为之后多态性的使用,提供了前提
多态性
体现
- 方法多态:重载和重写
- 对象的多态:父类的引用指向子类的对象(也可以说是子类的对象赋给父类的引用),即两个对象之间存在继承关系。
多态的产生
- Java中的引用变量的分为编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。
Person person=new Man();
//该语句的编译时类型就是Person,而运行时类型就是Man,编译时类型和运行时类型不一致,就出现了对象的多态性。
使用要点
1、对象的多态性只适合方法,并不适合属性。
2、使用多态性创建的父类引用不可以使用子类特有的方法。
3、如果子类重写了父类的方法,则在编译期不能确定调用的是哪一个方法(是父类的还是子类的),只有在运行期在可以确定(这也就是动态绑定)。
多态性的理解
1、为了实现代码的通用性。
2、常见使用多态性的地方:
Object类中定义的public boolean equals(Object obj){ }
JDBC:使用java程序操作(获取数据库连接、CRUD)数据库(MySQL、Oracle、DB2、SQL Server)
3、抽象类、接口的使用体现了多态性。(抽象类、接口不能实例化)
多态的向上转型
本质:父类的引用指向了子类的对象
语法:父类类型 引用名=new 子类类型():
特点:
- 编译类型看左边,运行类型看右边。
- 可以调用父类中的所有成员(需遵守访问权限)
- 不能调用子类中特有成员
- 最终运行结果看子类的具体实现!
多态的向下转型
语法:子类类型 引用名=(子类类型)父类引用:
特点:
- 只能强转父类的引用,不能强转父类的对象
- 要求父类的引用必须指向的是当前目标类型的对象
- 当向下转型后,可以调用子类类型中所有的成员
Animal animal=new Cat();
Cat cat=(Cat)animal;// OK
Dog dog=(Dog)animal;// 编译不通过
多态的应用
(1) 多态数组
数组定义为父类类型,实际可以存放子类类型
(2) 多态参数
形参定义为父类类型,实参可以传入子类类型