一、概述
1、定义
- 继承:就是子类继承父类的
属性和行为,使得子类对象具有父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。
2、好处
- 提高代码的复用性
- 类与类之间产生了关系,是多态的前提
二、继承的格式
通过extends关键字,可以声明一个子类继承另一个父类,定义格式如下:
class 父类{
...
}
class 子类 extends 父类{
...
}
举例:
// 定义一个员工类(父类)
public class Employee {
public void method(){
System.out.println("方法执行!");
}
}
// 定义一个教师类(子类)
// 定义了员工的子类:讲师
public class Teacher extends Employee{
}
// 定义一个测试类
public class Demo01Extends {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.method();
Assistant assistant = new Assistant();
assistant.method();
}
}
三、继承后的特点——成员变量
当类之间产生了关系后,其中各类中的成员变量,会产生哪些影响?
1、成员变量不重名
如果子类父类中出现不重名的成员变量,这时的访问是没有影响的。代码如下:
public class Employee {
// Employee中的成员变量
int age = 20;
}
// 定义了员工的子类:讲师
public class Teacher extends Employee{
int age_teacher = 35;
}
public class Demo02Extends {
public static void main(String[] args) {
// 创建父类对象
Employee e = new Employee();
System.out.println(e.age);
// 创建子类对象
Teacher teacher = new Teacher();
System.out.println(teacher.age);
System.out.println(teacher.age_teacher);
}
}
2、成员变量重名
如果子类父类中出现重名的成员变量,这时的访问是有影响的。代码如下:
public class Employee {
// Employee中的成员变量
int age = 20;
public void method(){
// 使用本类当中的age
System.out.println(age);
}
}
// 定义了员工的子类:讲师
public class Teacher extends Employee{
int age = 35;
public void method_teacher(){
// 因为本类当有 age, 所有优先使用本类的age
System.out.println(age);
}
}
package cn.wolfwotz.day05.Demo02;
// 父类子类成员变量重名
public class Demo03Extends {
public static void main(String[] args) {
// 创建父类对象
Employee e = new Employee();
System.out.println(e.age);
System.out.println("======");
// 创建子类对象
Teacher teacher = new Teacher();
System.out.println(teacher.age);// 优先使用子类, 35(通过对象名.成员变量,'.'左边是谁就优先用谁,没有则向上找)
System.out.println("======");
// 这个方法是子类的,优先使用子类的,没有再向上找
teacher.method_teacher(); // 35
// 这个方法是定义在父类当中的(该方法属于谁,就用谁,没有则向上找)
teacher.method();// 20
}
}
(1)、访问成员变量时:
- 直接通过子类对象访问成员变量
- ‘.’左边是谁,就优先用谁,没有则向上找父类
- 间接通过成员方法访问成员变量
- 该方法属于谁,就优先用谁,没有则想上找
(2)、区分局部变量、子类成员变量、父类成员变量
| 变量 | 写法 |
|---|---|
| 局部变量 | 直接写成员变量(num) |
| 子类成员变量 | this.成员变量(this.num) |
| 父类成员变量 | super.成员变量(super.num) |
public class Employee {
// Employee中的成员变量
int num = 10;
}
// 定义了员工的子类:讲师
public class Teacher extends Employee{
int num = 20;
public void method(){
int num = 30;
System.out.println(num); // 30, 局部变量
System.out.println(this.num); // 20 子类成员变量
System.out.println(super.num); // 10 父类成员变量
}
}
package cn.wolfwotz.day05.Demo02;
public class Demo04Extends {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.method();
}
}
四、继承后的特点——成员方法
当类之间产生了关系,其中各类的成员方法,又会产生哪些影响?
1、成员方法不重名
如果子类父类中出现不重名的成员方法,这时的调用是没有影响的。对象调用方法时,会现在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类不存在就会执行父类中相应的方法。
2、成员方法重名——重写(override)
如果子类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写(Override).
- 方法重写:子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也成为重写或者复写。声明不变,重新实现
public class SuperClass {
public void show(){
System.out.println("Superclass show");
}
}
public class SubClass {
// 子类重写父类方法
public void show(){
System.out.println("Subclass show");
}
}
public class Demo05Extends {
public static void main(String[] args) {
// 创建子类对象
SubClass sub = new SubClass();
// 子类 show function
sub.show(); // Subclass show
}
}
3、重写的应用
子类可以根据需要,定义特定于自己的行为,既沿袭了父类的功能名称,又根据子类的需要重新实现父类方法,从而进行拓展增强。
例:新的手机增加来电显示头像功能:
public class Phone {
public void sendMessage(){
System.out.println("发短信");
}
public void call(){
System.out.println("打电话");
}
public void showNum(){
System.out.println("来电显示");
}
}
public class NewPhone extends Phone{
// 重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
public void showNum(){
// 调用父类已经存在的功能
super.showNum();
// 增加自己特有的显示功能
System.out.println("显示来电姓名");
System.out.println("显示头像");
}
}
public class Demo06Extends {
public static void main(String[] args) {
// 创建子类对象
NewPhone np = new NewPhone();
// 调用父类继承而来的方法
np.call();
// 调用子类重写的方法
np.showNum();
}
}
这里重写时,用到super.父类成员方法,表示调用父类的成员方法
4、注意事项
子类方法覆盖父类方法,必须要保证权限大于等于父类权限(小拓展:public > protected > (default) > private)
备注:(default)不是关键字default,而是什么都不写
子类方法覆盖父类方法,函数名和参数列表都要一模一样
子类方法覆盖父类方法,子类方法的返回值必须小于等于父类方法的返回值范围
5、重写和重载的区别
- 重写(override):方法的名称一样,参数列表【也一样】
- 重载(overload):方法的名称一样,参数列表【不一样】
五、继承后的特点——构造方法
当类之间产生了关系,其中各类中的构造方法,又产生了哪些影响呢?
回忆构造方法的定义格式和作用:
- 构造方法的名字必须与类名字一致。所以子类是无法继承父类构造方法的
- 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个
super(),表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用
public class SuperClass {
public SuperClass(){
System.out.println("父类构造方法");
}
}
public class SubClass extends SuperClass{
public SubClass(){
// super(); // 在调用父类无参构造,不写也会有,编译器赠送
System.out.println("子类构造方法");
}
}
public class Demo07Extends {
public static void main(String[] args) {
SubClass sub = new SubClass();
}
}
输出结果:
父类构造方法
子类构造方法
1、特点
- 子类构造方法当中有一个默认隐含的
super()调用,所以一定是先调用的父类构造,后执行的子类构造 - 子类构造可以通过
super()关键字来调用父类重载构造 super的父类调用,必须是子类构造方法的第一个语句,不能一个子类构造多此super构造- 子类必须调用父类构造方法,不写则赠送
super(),写了则用写的指定的super调用,super只能有一个,还必须第一个
六、继承的特点
- Java只支持单继承,不支持多继承
// 一个类只能有一个父类,不可以有多个父类
class C extends A{}; // ok
class C extends A, B ... // error
- Java 支持多层继承(继承体系)
class A{}
class B extends A{}
class C extends B{}
- 子类和父类是一种相对的概念