面向对象高级 - 继承篇
01 什么是继承?
知识点讲解
继承是面向对象三大特征(封装、继承、多态)之一,是 Java 实现代码复用的核心机制。
- 定义:让一个类(子类 / 派生类)获得另一个类(父类 / 基类 / 超类)的属性和方法,子类可直接使用父类非私有成员,也可以扩展自己的特有功能。
- 关键字:
extends,语法:class 子类名 extends 父类名 { } - 核心价值:抽取共性代码,减少重复;为多态提供语法基础。
- 逻辑关系:必须满足 is-a(子类是父类的一种),例如 "猫是动物""学生是人"。
例题:动物类基础继承
需求:定义父类Animal(共性属性:姓名、年龄;共性方法:吃饭、睡觉),定义子类Cat和Dog,继承父类并添加特有行为。
java
// 父类:动物类
class Animal {
// 公共属性
String name;
int age;
// 公共方法
public void eat() {
System.out.println(name + "在吃饭");
}
public void sleep() {
System.out.println(name + "在睡觉,今年" + age + "岁");
}
}
// 子类:猫类,继承Animal
class Cat extends Animal {
// 子类特有方法
public void catchMouse() {
System.out.println(name + "在抓老鼠");
}
}
// 子类:狗类,继承Animal
class Dog extends Animal {
// 子类特有方法
public void lookHome() {
System.out.println(name + "在看家");
}
}
// 测试类
public class Demo01_ExtendsIntro {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "橘猫";
cat.age = 2;
cat.eat(); // 继承自父类
cat.sleep(); // 继承自父类
cat.catchMouse();// 子类特有
System.out.println("----------");
Dog dog = new Dog();
dog.name = "中华田园犬";
dog.age = 3;
dog.eat();
dog.sleep();
dog.lookHome();
}
}
运行结果:
plaintext
橘猫在吃饭
橘猫在睡觉,今年2岁
橘猫在抓老鼠
----------
中华田园犬在吃饭
中华田园犬在睡觉,今年3岁
中华田园犬在看家
02 如何设计一个复杂的继承体系?
知识点讲解
设计复杂继承体系的核心原则:共性向上抽取,特性向下扩展,形成层级化的类树。设计步骤:
- 梳理所有类的共性属性与方法,抽取到最顶层父类;
- 不同子类的特有属性与方法,留在子类中定义;
- 支持多层继承(爷爷类→父类→子类),逐级细化;
- 禁止为了复用代码强行继承,必须符合 "is-a" 逻辑。
典型场景:公司员工体系 → 顶层员工 → 细分正式员工 / 临时工 → 正式员工再细分研发 / 产品岗。
例题:公司员工继承体系
需求:设计三级员工继承体系:
- 顶层:
Employee(工号、姓名、基本工资;工作、领工资方法) - 二级:
FullTimeEmployee正式员工(年终奖;发年终奖方法)、PartTimeEmployee临时工(时薪、工时;结算薪资方法) - 三级:
Developer程序员(敲代码方法),继承正式员工
java
// 顶层父类:员工
class Employee {
String id; // 工号
String name; // 姓名
double salary; // 基本工资
public void work() {
System.out.println(name + "在上班工作");
}
public void getSalary() {
System.out.println(name + "领取基本工资:" + salary + "元");
}
}
// 子类:正式员工
class FullTimeEmployee extends Employee {
double yearBonus; // 年终奖
public void getYearBonus() {
System.out.println(name + "领取年终奖:" + yearBonus + "元");
}
}
// 子类:临时工
class PartTimeEmployee extends Employee {
double hourSalary; // 时薪
int workHours; // 工作时长
public void calcHourSalary() {
double total = hourSalary * workHours;
System.out.println(name + "临时工结算薪资:" + total + "元");
}
}
// 正式员工的子类:程序员
class Developer extends FullTimeEmployee {
public void coding() {
System.out.println(name + "程序员在写Java代码");
}
}
// 测试类
public class Demo02_ExtendsDesign {
public static void main(String[] args) {
Developer dev = new Developer();
dev.id = "R001";
dev.name = "张三";
dev.salary = 12000;
dev.yearBonus = 36000;
dev.work(); // 爷爷类方法
dev.getSalary(); // 爷爷类方法
dev.getYearBonus();// 父类方法
dev.coding(); // 自身方法
System.out.println("----------");
PartTimeEmployee pt = new PartTimeEmployee();
pt.name = "李四";
pt.hourSalary = 80;
pt.workHours = 120;
pt.work();
pt.calcHourSalary();
}
}
运行结果:
plaintext
张三在上班工作
张三领取基本工资:12000.0元
张三领取年终奖:36000.0元
张三程序员在写Java代码
----------
李四在上班工作
李四临时工结算薪资:9600.0元
03 继承的特点
知识点讲解
Java 继承有三个核心规则:
- 单继承限制 :一个类只能有一个直接父类(不支持多继承,避免多个父类同名方法冲突);
- 多层继承:支持间接继承(爷爷类、曾祖父类),子类可继承整条继承链上的非私有成员;
- Object 根类 :所有类都直接或间接继承自
java.lang.Object,它是 Java 所有类的根父类。
补充:一个父类可以拥有多个子类。
例题:验证继承三大特点
需求:设计A→B→C多层继承,验证单继承、多层继承、Object 根类特性。
java
// 顶层类A(默认继承Object)
class A {
public void methodA() {
System.out.println("A类的方法");
}
}
// B类继承A(单继承,只能写一个父类)
class B extends A {
public void methodB() {
System.out.println("B类的方法");
}
}
// C类继承B(多层继承,间接继承A和Object)
class C extends B {
public void methodC() {
System.out.println("C类的方法");
}
}
// 测试类
public class Demo03_ExtendsFeature {
public static void main(String[] args) {
C c = new C();
// 可调用自身、父类B、爷爷类A的方法
c.methodC();
c.methodB();
c.methodA();
// 所有类都继承Object,可调用Object方法,例如toString()
System.out.println("Object类的toString方法:" + c.toString());
// 错误写法(编译不通过):Java不支持多继承
// class D extends A, B {}
}
}
运行结果:
plaintext
C类的方法
B类的方法
A类的方法
Object类的toString方法:C@1b6d3586
04 继承中成员变量的特点
知识点讲解
当子类与父类出现同名成员变量时,遵循就近原则:
- 子类方法访问变量:先找方法局部变量 → 再找子类成员变量 → 再找父类成员变量,都没有则编译报错;
- 访问父类同名变量:使用
super.变量名; - 同名现象叫变量隐藏,父子类的变量同时存在,不是覆盖。
super关键字:代表父类对象的引用,用于访问父类的成员变量、成员方法、构造方法。
例题:变量就近原则与 super 使用
需求:父子类定义同名变量num,演示局部变量、子类变量、父类变量的访问区别。
java
// 父类
class Father {
int num = 100; // 父类成员变量
String name = "父亲";
}
// 子类
class Son extends Father {
int num = 200; // 子类同名成员变量
public void show() {
int num = 300; // 方法局部变量
System.out.println("局部变量num:" + num); // 就近:300
System.out.println("子类成员变量num:" + this.num); // 子类:200
System.out.println("父类成员变量num:" + super.num);// 父类:100
// 无同名变量时,直接向上找父类
System.out.println("父类的name:" + name);
}
}
// 测试类
public class Demo04_VariableInExtends {
public static void main(String[] args) {
Son son = new Son();
son.show();
}
}
运行结果:
plaintext
局部变量num:300
子类成员变量num:200
父类成员变量num:100
父类的name:父亲
05 继承中成员方法的特点(方法重写)
知识点讲解
子类中出现与父类方法声明完全一致 (方法名、参数列表、返回值类型都相同)的方法,叫做方法重写(Override),也叫方法覆盖。
重写规则
- 方法名、参数列表必须与父类完全一致;
- 子类方法权限 >= 父类方法权限(
public>protected> 默认 >private); - 引用类型返回值,子类可以是父类返回值的子类;基本类型必须完全相同;
- private 方法、静态方法不能被重写。
@Override 注解
写在子类方法上方,用于检测该方法是否符合重写规则,语法错误会直接编译报错,提升代码安全性。
重写 vs 重载
- 重写:父子类之间,方法名 + 参数列表完全相同,是方法的 "覆盖";
- 重载:同一个类中,方法名相同、参数列表不同,是方法的 "多版本"。
例题:方法重写与 super 调用父类方法
需求:父类Phone有打电话、发短信方法,子类NewPhone重写方法,扩展新功能,并用 super 保留父类原有逻辑。
java
// 父类:旧手机
class Phone {
public void call() {
System.out.println("打电话:语音通话");
}
public void sendMessage() {
System.out.println("发短信:文字短信");
}
}
// 子类:新手机
class NewPhone extends Phone {
// 重写call方法,添加视频通话
@Override // 重写校验注解
public void call() {
super.call(); // 保留父类原有功能
System.out.println("升级:支持视频通话");
}
// 重写发短信方法
@Override
public void sendMessage() {
super.sendMessage();
System.out.println("升级:支持发送图片、表情");
}
}
// 测试类
public class Demo05_MethodOverride {
public static void main(String[] args) {
NewPhone phone = new NewPhone();
phone.call();
System.out.println("----------");
phone.sendMessage();
}
}
运行结果:
plaintext
打电话:语音通话
升级:支持视频通话
----------
发短信:文字短信
升级:支持发送图片、表情
06 继承中构造方法的特点
知识点讲解
子类构造方法执行时,一定会先执行父类构造方法------ 子类继承了父类成员,需要先完成父类成员的初始化。
核心规则
- 子类构造方法第一行,默认隐藏
super();,自动调用父类无参构造; - 若父类没有无参构造,子类必须通过
super(参数);手动调用父类有参构造,否则编译报错; super()和this()都必须写在构造方法第一行,因此两者不能同时出现;- 构造方法不能被继承,只能被调用。
例题:构造方法调用顺序
需求:父类Person有无参、有参构造,子类Student有多个构造方法,演示执行顺序与 super 传参。
java
// 父类
class Person {
String name;
int age;
// 父类无参构造
public Person() {
System.out.println("父类Person的无参构造执行了");
}
// 父类有参构造
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("父类Person的有参构造执行了");
}
}
// 子类
class Student extends Person {
int score;
// 子类无参构造
public Student() {
// 默认隐藏 super(); 调用父类无参
System.out.println("子类Student的无参构造执行了");
}
// 子类有参构造
public Student(String name, int age, int score) {
// 手动调用父类有参构造,给父类属性赋值
super(name, age);
this.score = score;
System.out.println("子类Student的有参构造执行了");
}
public void show() {
System.out.println("姓名:" + name + ",年龄:" + age + ",成绩:" + score);
}
}
// 测试类
public class Demo06_ConstructorInExtends {
public static void main(String[] args) {
System.out.println("=== 创建无参学生对象 ===");
Student s1 = new Student();
System.out.println("\n=== 创建有参学生对象 ===");
Student s2 = new Student("小明", 18, 95);
s2.show();
}
}
运行结果:
plaintext
=== 创建无参学生对象 ===
父类Person的无参构造执行了
子类Student的无参构造执行了
=== 创建有参学生对象 ===
父类Person的有参构造执行了
子类Student的有参构造执行了
姓名:小明,年龄:18,成绩:95
07 带有继承结构的标准 JavaBean
知识点讲解
标准 JavaBean(实体类)开发规范:
- 成员变量全部使用
private修饰(封装); - 为每个成员变量提供
getXxx和setXxx方法; - 提供无参构造方法 + 全参构造方法;
- 建议重写
toString()方法,方便打印对象信息。
继承体系下的 JavaBean:
- 父类按规范编写自身的属性、get/set、构造方法;
- 子类继承父类,编写自身特有属性、get/set,构造方法通过
super调用父类构造。
例题:继承体系下的标准 JavaBean
需求:编写标准父类Person、子类Teacher,完全符合 JavaBean 规范。
java
// 标准父类JavaBean
class Person {
// 1.私有成员变量
private String name;
private int age;
// 2.无参构造
public Person() {
}
// 3.全参构造
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 4.get/set方法
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;
}
// 5.重写toString
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
// 标准子类JavaBean
class Teacher extends Person {
// 子类特有私有属性
private double salary;
// 子类无参构造
public Teacher() {
}
// 子类全参构造:调用父类有参构造
public Teacher(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
// 子类属性的get/set
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
// 重写toString,拼接父子类信息
@Override
public String toString() {
return "Teacher{name='" + getName() + "', age=" + getAge() + ", salary=" + salary + "}";
}
}
// 测试类
public class Demo07_StandardJavaBean {
public static void main(String[] args) {
// 无参构造 + set赋值
Teacher t1 = new Teacher();
t1.setName("王老师");
t1.setAge(35);
t1.setSalary(8000);
System.out.println(t1);
// 全参构造直接赋值
Teacher t2 = new Teacher("李老师", 28, 6500);
System.out.println(t2);
}
}
运行结果:
plaintext
Teacher{name='王老师', age=35, salary=8000.0}
Teacher{name='李老师', age=28, salary=6500.0}
08 继承的作业
知识点讲解
本节通过编程作业综合巩固:继承定义、成员变量、成员方法、方法重写的组合使用。
作业例题:图形类继承练习
需求:
- 父类
Shape(图形):属性color;方法getArea()返回面积、getPerimeter()返回周长(默认返回 0) - 子类
Circle(圆形):特有属性radius半径;重写面积、周长方法 - 子类
Rectangle(矩形):特有属性length长、width宽;重写面积、周长方法 - 创建对象测试计算结果
java
// 父类:图形
class Shape {
String color;
public double getArea() {
return 0;
}
public double getPerimeter() {
return 0;
}
}
// 子类:圆形
class Circle extends Shape {
double radius;
public Circle(double radius, String color) {
this.radius = radius;
this.color = color;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
@Override
public double getPerimeter() {
return 2 * Math.PI * radius;
}
}
// 子类:矩形
class Rectangle extends Shape {
double length;
double width;
public Rectangle(double length, double width, String color) {
this.length = length;
this.width = width;
this.color = color;
}
@Override
public double getArea() {
return length * width;
}
@Override
public double getPerimeter() {
return 2 * (length + width);
}
}
// 测试类
public class Demo08_ExtendsHomework {
public static void main(String[] args) {
Circle circle = new Circle(5, "红色");
System.out.println("圆形颜色:" + circle.color);
System.out.println("圆形面积:" + String.format("%.2f", circle.getArea()));
System.out.println("圆形周长:" + String.format("%.2f", circle.getPerimeter()));
System.out.println("----------");
Rectangle rect = new Rectangle(4, 6, "蓝色");
System.out.println("矩形颜色:" + rect.color);
System.out.println("矩形面积:" + rect.getArea());
System.out.println("矩形周长:" + rect.getPerimeter());
}
}
运行结果:
plaintext
圆形颜色:红色
圆形面积:78.54
圆形周长:31.42
----------
矩形颜色:蓝色
矩形面积:24.0
矩形周长:20.0
09 子类到底能继承父类的什么?
知识点讲解
子类不是父类所有内容都能继承,访问权限受修饰符限制:
表格
| 成员类型 | 能否直接访问 | 说明 |
|---|---|---|
| public 成员变量 / 方法 | ✅ 可以 | 任意位置都能访问 |
| protected 成员变量 / 方法 | ✅ 可以 | 子类中可直接访问,不同包子类也可 |
| 默认(包访问)成员 | 同包✅ / 不同包❌ | 父子类同包可直接访问,不同包不行 |
| private 成员变量 / 方法 | ❌ 不能直接访问 | 只能在父类内部访问,子类需通过 get/set 间接操作 |
补充:
- 父类构造方法不能继承 ,只能通过
super调用; - 静态成员属于类本身,不存在 "继承" 概念,属于类共享。
例题:私有成员的访问验证
需求:父类定义私有属性,演示子类不能直接访问,必须通过 get/set 间接操作。
java
// 父类
class Parent {
public String publicVar = "公共变量";
private int privateVar = 100; // 私有变量
public void publicMethod() {
System.out.println("父类公共方法");
}
private void privateMethod() {
System.out.println("父类私有方法");
}
// 提供get/set访问私有变量
public int getPrivateVar() {
return privateVar;
}
public void setPrivateVar(int privateVar) {
this.privateVar = privateVar;
}
}
// 子类
class Child extends Parent {
public void show() {
System.out.println("直接访问父类公共变量:" + publicVar);
// 编译报错:不能直接访问父类私有变量
// System.out.println(privateVar);
// 通过get方法间接访问
System.out.println("通过get访问父类私有变量:" + getPrivateVar());
publicMethod(); // 可调用父类公共方法
// 编译报错:不能调用父类私有方法
// privateMethod();
}
}
// 测试类
public class Demo09_WhatCanInherit {
public static void main(String[] args) {
Child child = new Child();
child.show();
// 通过set修改父类私有变量
child.setPrivateVar(200);
System.out.println("修改后父类私有变量值:" + child.getPrivateVar());
}
}
运行结果:
plaintext
直接访问父类公共变量:公共变量
通过get访问父类私有变量:100
父类公共方法
修改后父类私有变量值:200
10 Java 中的权限修饰符
知识点讲解
Java 有 4 种权限修饰符,权限从大到小:public > protected > 默认(空) > private
访问范围对照表:
表格
| 修饰符 | 本类中 | 同包下 | 不同包的子类 | 不同包无关类 |
|---|---|---|---|---|
| public | ✅ | ✅ | ✅ | ✅ |
| protected | ✅ | ✅ | ✅ | ❌ |
| 默认(包访问) | ✅ | ✅ | ❌ | ❌ |
| private | ✅ | ❌ | ❌ | ❌ |
使用建议:
- 成员变量:一般用
private封装,通过 get/set 对外暴露; - 成员方法:对外功能用
public,子类重写用protected,本包内部用默认; - 普通类:只能用
public或默认,不能用 protected/private(内部类除外)。
例题:权限修饰符访问验证
需求:在同包环境下,验证本类、子类、无关类对不同权限成员的访问能力。
java
// 父类(同包)
class ModifierDemo {
public int a = 1; // 公共
protected int b = 2; // 受保护
int c = 3; // 默认
private int d = 4; // 私有
public void test() {
// 本类中:所有权限都能访问
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
}
// 同包下的子类
class SubSamePackage extends ModifierDemo {
public void show() {
System.out.println("同包子类访问public:" + a);
System.out.println("同包子类访问protected:" + b);
System.out.println("同包子类访问默认:" + c);
// System.out.println(d); // 编译报错,private不可访问
}
}
// 同包下的无关类
class OtherSamePackage {
public void show() {
ModifierDemo demo = new ModifierDemo();
System.out.println("同包无关类访问public:" + demo.a);
System.out.println("同包无关类访问protected:" + demo.b);
System.out.println("同包无关类访问默认:" + demo.c);
// System.out.println(demo.d); // 编译报错,private不可访问
}
}
// 测试类
public class Demo10_PermissionModifier {
public static void main(String[] args) {
System.out.println("=== 本类测试 ===");
ModifierDemo demo = new ModifierDemo();
demo.test();
System.out.println("\n=== 同包子类测试 ===");
SubSamePackage sub = new SubSamePackage();
sub.show();
System.out.println("\n=== 同包无关类测试 ===");
OtherSamePackage other = new OtherSamePackage();
other.show();
}
}
运行结果:
plaintext
=== 本类测试 ===
1
2
3
4
=== 同包子类测试 ===
同包子类访问public:1
同包子类访问protected:2
同包子类访问默认:3
=== 同包无关类测试 ===
同包无关类访问public:1
同包无关类访问protected:2
同包无关类访问默认:3
本章综合练习题(5 道,难度递进)
综合题 1(基础难度)
题目 :定义父类Vehicle(交通工具),属性:品牌brand、价格price;方法:运行run()。定义子类Car,继承 Vehicle,特有属性:座位数seatCount;特有方法:载人carryPeople()。创建 Car 对象,调用所有属性和方法。
java
class Vehicle {
String brand;
double price;
public void run() {
System.out.println(brand + "交通工具正在行驶,售价" + price + "元");
}
}
class Car extends Vehicle {
int seatCount;
public void carryPeople() {
System.out.println("这辆" + brand + "汽车可以载" + seatCount + "个人");
}
}
public class Exam01_Basic {
public static void main(String[] args) {
Car car = new Car();
car.brand = "比亚迪";
car.price = 159800;
car.seatCount = 5;
car.run();
car.carryPeople();
}
}
运行结果:
plaintext
比亚迪交通工具正在行驶,售价159800.0元
这辆比亚迪汽车可以载5个人
综合题 2(中等难度)
题目 :设计多层继承体系:Food(食物)→ Fruit(水果)→ Apple(苹果)。
- Food:属性
name,方法taste()输出 "食物有味道" - Fruit:新增属性
isSweet,重写taste() - Apple:新增属性
color,重写taste(),新增方法makeJuice()创建 Apple 对象,测试所有属性和方法。
java
class Food {
String name;
public void taste() {
System.out.println(name + ":食物有味道");
}
}
class Fruit extends Food {
boolean isSweet;
@Override
public void taste() {
System.out.println(name + "是水果," + (isSweet ? "味道很甜" : "味道不甜"));
}
}
class Apple extends Fruit {
String color;
@Override
public void taste() {
System.out.println(color + "的" + name + "," + (isSweet ? "脆甜多汁" : "酸酸的"));
}
public void makeJuice() {
System.out.println("用" + name + "榨苹果汁");
}
}
public class Exam02_Medium {
public static void main(String[] args) {
Apple apple = new Apple();
apple.name = "红富士";
apple.isSweet = true;
apple.color = "红色";
apple.taste();
apple.makeJuice();
}
}
运行结果:
plaintext
红色的红富士,脆甜多汁
用红富士榨苹果汁
综合题 3(进阶难度)
题目:按照标准 JavaBean 规范,设计员工继承体系:
- 父类
Staff:私有属性id、name、baseSalary;无参、全参构造;get/set;重写 toString - 子类
Salesman(销售员):私有属性saleAmount(销售额)、commissionRate(提成比例);无参、全参构造;get/set;重写 toString;方法calcSalary()计算薪资(薪资 = 基础工资 + 销售额 * 提成比例)
java
class Staff {
private String id;
private String name;
private double baseSalary;
public Staff() {
}
public Staff(String id, String name, double baseSalary) {
this.id = id;
this.name = name;
this.baseSalary = baseSalary;
}
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getBaseSalary() { return baseSalary; }
public void setBaseSalary(double baseSalary) { this.baseSalary = baseSalary; }
@Override
public String toString() {
return "员工{工号='" + id + "', 姓名='" + name + "', 基本工资=" + baseSalary + "}";
}
}
class Salesman extends Staff {
private double saleAmount;
private double commissionRate;
public Salesman() {
}
public Salesman(String id, String name, double baseSalary, double saleAmount, double commissionRate) {
super(id, name, baseSalary);
this.saleAmount = saleAmount;
this.commissionRate = commissionRate;
}
public double getSaleAmount() { return saleAmount; }
public void setSaleAmount(double saleAmount) { this.saleAmount = saleAmount; }
public double getCommissionRate() { return commissionRate; }
public void setCommissionRate(double commissionRate) { this.commissionRate = commissionRate; }
// 计算总薪资
public double calcSalary() {
return getBaseSalary() + saleAmount * commissionRate;
}
@Override
public String toString() {
return "销售员{工号='" + getId() + "', 姓名='" + getName() +
"', 基本工资=" + getBaseSalary() +
", 销售额=" + saleAmount + ", 提成比例=" + commissionRate + "}";
}
}
public class Exam03_Advanced {
public static void main(String[] args) {
Salesman s = new Salesman("S001", "赵六", 5000, 80000, 0.1);
System.out.println(s);
System.out.println("本月总薪资:" + s.calcSalary() + "元");
}
}
运行结果:
plaintext
销售员{工号='S001', 姓名='赵六', 基本工资=5000.0, 销售额=80000.0, 提成比例=0.1}
本月总薪资:13000.0元
综合题 4(较难难度)
题目:设计学校人员继承体系,结合方法重写、super 调用、权限修饰符:
- 父类
SchoolPerson:protected 属性name、age;方法introduce()介绍自己 - 子类
Student:特有属性stuId、grade;重写introduce(),调用父类方法并补充学生信息 - 子类
Teacher:特有属性subject、title;重写introduce(),调用父类方法并补充教师信息
java
class SchoolPerson {
protected String name;
protected int age;
public SchoolPerson(String name, int age) {
this.name = name;
this.age = age;
}
public void introduce() {
System.out.println("大家好,我叫" + name + ",今年" + age + "岁");
}
}
class Student extends SchoolPerson {
private String stuId;
private String grade;
public Student(String name, int age, String stuId, String grade) {
super(name, age);
this.stuId = stuId;
this.grade = grade;
}
@Override
public void introduce() {
super.introduce();
System.out.println("我是" + grade + "的学生,学号是" + stuId);
}
}
class Teacher extends SchoolPerson {
private String subject;
private String title;
public Teacher(String name, int age, String subject, String title) {
super(name, age);
this.subject = subject;
this.title = title;
}
@Override
public void introduce() {
super.introduce();
System.out.println("我是教" + subject + "的" + title);
}
}
public class Exam04_Hard {
public static void main(String[] args) {
Student stu = new Student("小红", 16, "2024001", "高一");
stu.introduce();
System.out.println("----------");
Teacher tea = new Teacher("张老师", 40, "数学", "高级教师");
tea.introduce();
}
}
运行结果:
plaintext
大家好,我叫小红,今年16岁
我是高一的学生,学号是2024001
----------
大家好,我叫张老师,今年40岁
我是教数学的高级教师
综合题 5(最难,全知识点综合)
题目:设计电商商品继承体系,综合封装、继承、方法重写、构造方法、权限修饰符所有知识点:
- 顶层父类
Product:- 私有属性:商品 id、名称、价格
- 无参、全参构造,get/set 方法
- 方法:
showInfo()展示基础信息;calcTotalPrice(int count)计算总价(价格 * 数量)
- 子类
Electronics(电子产品):- 新增私有属性:品牌、保修期(月)
- 重写
showInfo()补充电子商品信息 - 重写
calcTotalPrice:满 1000 减 50
- 子类
Clothing(服装):- 新增私有属性:尺码、颜色
- 重写
showInfo()补充服装信息 - 重写
calcTotalPrice:买 2 件以上打 9 折
- 创建两个子类对象,分别调用展示信息和购买 5 件的总价。
java
class Product {
private String id;
private String name;
private double price;
public Product() {
}
public Product(String id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
public void showInfo() {
System.out.println("商品编号:" + id);
System.out.println("商品名称:" + name);
System.out.println("商品单价:" + price + "元");
}
public double calcTotalPrice(int count) {
return price * count;
}
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
}
class Electronics extends Product {
private String brand;
private int warrantyMonths;
public Electronics() {
}
public Electronics(String id, String name, double price, String brand, int warrantyMonths) {
super(id, name, price);
this.brand = brand;
this.warrantyMonths = warrantyMonths;
}
@Override
public void showInfo() {
super.showInfo();
System.out.println("品牌:" + brand);
System.out.println("保修期:" + warrantyMonths + "个月");
}
// 满1000减50
@Override
public double calcTotalPrice(int count) {
double total = super.calcTotalPrice(count);
if (total >= 1000) {
total -= 50;
}
return total;
}
public String getBrand() { return brand; }
public void setBrand(String brand) { this.brand = brand; }
public int getWarrantyMonths() { return warrantyMonths; }
public void setWarrantyMonths(int warrantyMonths) { this.warrantyMonths = warrantyMonths; }
}
class Clothing extends Product {
private String size;
private String color;
public Clothing() {
}
public Clothing(String id, String name, double price, String size, String color) {
super(id, name, price);
this.size = size;
this.color = color;
}
@Override
public void showInfo() {
super.showInfo();
System.out.println("尺码:" + size);
System.out.println("颜色:" + color);
}
// 买2件以上打9折
@Override
public double calcTotalPrice(int count) {
double total = super.calcTotalPrice(count);
if (count >= 2) {
total *= 0.9;
}
return total;
}
public String getSize() { return size; }
public void setSize(String size) { this.size = size; }
public String getColor() { return color; }
public void setColor(String color) { this.color = color; }
}
public class Exam05_Master {
public static void main(String[] args) {
System.out.println("===== 电子产品 =====");
Electronics phone = new Electronics("E001", "智能手机", 2999, "小米", 12);
phone.showInfo();
System.out.println("购买5台总价:" + phone.calcTotalPrice(5) + "元");
System.out.println("\n===== 服装 =====");
Clothing shirt = new Clothing("C001", "纯棉衬衫", 199, "XL", "白色");
shirt.showInfo();
System.out.println("购买5件总价:" + shirt.calcTotalPrice(5) + "元");
}
}
运行结果:
plaintext
===== 电子产品 =====
商品编号:E001
商品名称:智能手机
商品单价:2999.0元
品牌:小米
保修期:12个月
购买5台总价:14945.0元
===== 服装 =====
商品编号:C001
商品名称:纯棉衬衫
商品单价:199.0元
尺码:XL
颜色:白色
购买5件总价:895.5元