跟der包学习java_day8「继承(Inheritance)」

今日目标

理解继承的意义和核心作用(代码复用、扩展)掌握继承的语法(
extends
关键字)理解父类与子类的关系,以及方法重写(
@Override
)了解
super
关键字的用法

一、为什么需要继承?

假设我们要定义 “学生类” 和 “老师类”,它们的代码可能是这样的:



// 学生类
class Student {
    private String name; // 姓名
    private int age;     // 年龄
    
    // getter/setter
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    
    // 学生独有的方法
    public void study() {
        System.out.println(name + "在学习");
    }
}
 
// 老师类
class Teacher {
    private String name; // 姓名(和Student重复)
    private int age;     // 年龄(和Student重复)
    
    // getter/setter(和Student重复)
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    
    // 老师独有的方法
    public void teach() {
        System.out.println(name + "在讲课");
    }
}

问题:两个类都有
name

age
属性和对应的
getter/setter
,代码重复,维护成本高(比如修改
name
的逻辑,需要改两个类)。

继承的解决思路:提取共同部分,定义一个 “父类(如 Person 类)”,让 Student 和 Teacher “继承” 这个父类,从而复用父类的属性和方法,只关注自己独有的内容。

二、继承的基本语法

1. 定义父类(超类、基类)


// 父类:封装学生和老师的共同属性和方法
class Person {
    private String name;
    private int age;
    
    // 构造方法
    public Person() {}
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // getter/setter
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    
    // 共同的方法(比如吃饭)
    public void eat() {
        System.out.println(name + "在吃饭");
    }
}
2. 子类继承父类(用
extends
关键字)


// 学生类继承Person类
class Student extends Person {
    // 子类可以直接使用父类的属性和方法(无需重复定义)
    
    // 学生独有的属性(比如学号)
    private String studentId;
    
    // 学生独有的方法
    public void study() {
        // 可以调用父类的getName()方法
        System.out.println(getName() + "在学习");
    }
    
    // 学生独有的getter/setter
    public String getStudentId() { return studentId; }
    public void setStudentId(String studentId) { this.studentId = studentId; }
}
 
// 老师类继承Person类
class Teacher extends Person {
    // 老师独有的属性(比如工号)
    private String teacherId;
    
    // 老师独有的方法
    public void teach() {
        System.out.println(getName() + "在讲课");
    }
    
    // 老师独有的getter/setter
    public String getTeacherId() { return teacherId; }
    public void setTeacherId(String teacherId) { this.teacherId = teacherId; }
}
3. 使用子类对象


public class TestInheritance {
    public static void main(String[] args) {
        // 创建学生对象
        Student stu = new Student();
        // 调用父类的setter(继承而来)
        stu.setName("张三");
        stu.setAge(18);
        // 调用子类独有的setter
        stu.setStudentId("S001");
        // 调用父类的方法(继承而来)
        stu.eat(); // 输出:张三在吃饭
        // 调用子类独有的方法
        stu.study(); // 输出:张三在学习
        
        // 创建老师对象
        Teacher tea = new Teacher();
        tea.setName("李四");
        tea.eat(); // 输出:李四在吃饭
        tea.teach(); // 输出:李四在讲课
    }
}

继承的好处

代码复用:子类无需重复定义父类已有的属性和方法。代码扩展:子类可以在父类基础上添加新的属性和方法。形成层次:类之间的继承关系(如 “Person→Student”)更符合现实世界的分类逻辑。

三、方法重写(Override)

子类继承父类后,如果父类的方法不能满足子类的需求,可以重写父类的方法(覆盖父类的实现)。

重写的规则:

方法名、参数列表必须完全相同(和父类一致)。返回值类型:子类返回值类型必须是父类返回值类型的子类或相同(基本类型必须相同)。访问修饰符:子类方法的访问权限不能低于父类(如父类是
protected
,子类可以是
protected

public
,不能是
private
)。用
@Override
注解标记(可选,但推荐,编译器会检查是否符合重写规则)。

示例:重写父类的
eat
方法


class Person {
    public void eat() {
        System.out.println("人在吃饭");
    }
}
 
class Student extends Person {
    // 重写父类的eat方法(学生吃饭有自己的特点)
    @Override
    public void eat() {
        System.out.println("学生在食堂吃饭");
    }
}
 
class Teacher extends Person {
    // 重写父类的eat方法
    @Override
    public void eat() {
        System.out.println("老师在办公室吃饭");
    }
}
 
// 测试
public class TestOverride {
    public static void main(String[] args) {
        Person p = new Person();
        p.eat(); // 输出:人在吃饭
        
        Student s = new Student();
        s.eat(); // 输出:学生在食堂吃饭(调用重写后的方法)
        
        Teacher t = new Teacher();
        t.eat(); // 输出:老师在办公室吃饭(调用重写后的方法)
    }
}

重写的意义:实现 “多态” 的基础(后续会学),让不同子类对同一方法有不同实现。

四、
super
关键字


super
用于访问父类的属性、方法或构造方法,类似于
this

this
指当前对象,
super
指父类对象)。

1. 调用父类的方法


class Person {
    public void eat() {
        System.out.println("人在吃饭");
    }
}
 
class Student extends Person {
    @Override
    public void eat() {
        super.eat(); // 调用父类的eat方法
        System.out.println("学生在食堂吃饭"); // 新增子类逻辑
    }
}
 
// 测试
Student s = new Student();
s.eat(); 
// 输出:
// 人在吃饭
// 学生在食堂吃饭
2. 调用父类的构造方法

子类构造方法中,默认会先调用父类的无参构造方法(隐式调用
super()
)。如果父类没有无参构造,必须在子类构造方法的第一行显式调用父类的有参构造(
super(参数)
)。



class Person {
    private String name;
    
    // 父类只有有参构造(没有无参构造)
    public Person(String name) {
        this.name = name;
    }
}
 
class Student extends Person {
    private String studentId;
    
    // 子类构造方法必须显式调用父类的有参构造
    public Student(String name, String studentId) {
        super(name); // 调用父类的有参构造(必须在第一行)
        this.studentId = studentId;
    }
}

注意
super()

this()
(调用本类其他构造)不能同时出现,且都必须放在构造方法的第一行。

五、继承的限制

单继承:Java 中一个类只能直接继承一个父类(避免多继承的复杂性),但可以多层继承(如
A→B→C
,C 继承 B,B 继承 A)。

私有成员不可直接访问:子类不能直接访问父类的
private
属性和方法(需通过父类的
public
/
protected
方法间接访问)。



class Person {
    private int age; // 私有属性
    
    public int getAge() { return age; } // 公共方法
}
 
class Student extends Person {
    public void showAge() {
        // System.out.println(age); // 错误:不能直接访问父类private属性
        System.out.println(getAge()); // 正确:通过父类的public方法访问
    }
}

构造方法不能继承:子类可以调用父类的构造方法,但不能继承。

六、练习

继承基础:定义一个 “动物类(Animal)”,包含属性
name
,方法
shout()
(输出 “动物叫”)。定义 “狗类(Dog)” 和 “猫类(Cat)” 继承 Animal,分别重写
shout()
方法(狗输出 “汪汪叫”,猫输出 “喵喵叫”),并测试。


super
练习
:在上面的 Dog 类中,重写
shout()
时,先调用父类的
shout()
,再输出 “汪汪叫”(最终效果:“动物叫 汪汪叫”)。

今日总结

继承通过
extends
关键字实现,子类复用父类的属性和方法,添加独有内容。方法重写:子类重写父类方法(方法名、参数相同),实现个性化逻辑,用
@Override
标记。
super
关键字
:访问父类的属性、方法或构造方法(
super()
调用父类构造,需在子类构造第一行)。继承限制:单继承、私有成员不可直接访问、构造方法不能继承。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容