今日目标
理解继承的意义和核心作用(代码复用、扩展)掌握继承的语法(关键字)理解父类与子类的关系,以及方法重写(
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关键字)
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方法
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
用于访问父类的属性、方法或构造方法,类似于
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 中一个类只能直接继承一个父类(避免多继承的复杂性),但可以多层继承(如,C 继承 B,B 继承 A)。
A→B→C
私有成员不可直接访问:子类不能直接访问父类的属性和方法(需通过父类的
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(输出 “动物叫”)。定义 “狗类(Dog)” 和 “猫类(Cat)” 继承 Animal,分别重写
shout()方法(狗输出 “汪汪叫”,猫输出 “喵喵叫”),并测试。
shout()
练习:在上面的 Dog 类中,重写
super时,先调用父类的
shout(),再输出 “汪汪叫”(最终效果:“动物叫 汪汪叫”)。
shout()
今日总结
继承通过关键字实现,子类复用父类的属性和方法,添加独有内容。方法重写:子类重写父类方法(方法名、参数相同),实现个性化逻辑,用
extends标记。
@Override关键字:访问父类的属性、方法或构造方法(
super调用父类构造,需在子类构造第一行)。继承限制:单继承、私有成员不可直接访问、构造方法不能继承。
super()


















暂无评论内容