Java 继承:构建代码复用与层级关系的艺术

在 Java 的面向对象世界中,继承就像现实世界的 "父子关系" 一样,让类与类之间建立起自然的层级联系。当你需要创建 "学生" 和 "教师" 类时,不必重复编写 "姓名"、"年龄" 等共同属性,通过继承 "人" 类就能轻松实现代码复用。这种特性不仅减少了重复劳动,更让系统架构呈现出清晰的逻辑层次。

一、继承的基本语法与本质

Java 通过extends关键字实现继承,子类(subclass)将获得父类(superclass)的非私有成员:

// 父类
public class Person {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public void eat() {
        System.out.println(name + "正在吃饭");
    }
    
    public String getName() {
        return name;
    }
    
    // getter和setter省略
}

// 子类继承父类
public class Student extends Person {
    private String studentId;
    private String major;
    
    // 子类构造器必须调用父类构造器
    public Student(String name, int age, String studentId, String major) {
        super(name, age); // 调用父类构造器
        this.studentId = studentId;
        this.major = major;
    }
    
    // 子类特有方法
    public void study() {
        System.out.println(getName() + "正在学习" + major + "专业");
    }
}

继承的本质是 "is-a" 关系:Student is a Person,这种语义约束确保了继承关系的合理性。Java 只支持单继承(一个类只能有一个直接父类),但通过接口可以实现类似多继承的效果。

二、方法重写:继承中的多态基础

子类可以重写(override)父类的方法,实现符合自身特性的行为:

public class Teacher extends Person {
    private String subject;
    
    public Teacher(String name, int age, String subject) {
        super(name, age);
        this.subject = subject;
    }
    
    // 重写父类的eat方法
    @Override
    public void eat() {
        System.out.println(getName() + "快速地吃饭,因为要赶去上课");
    }
    
    // 新增特有方法
    public void teach() {
        System.out.println(getName() + "正在教授" + subject + "课程");
    }
}

方法重写需遵循 "两同两小一大" 原则:

  • 方法名和参数列表相同
  • 返回值类型小于等于父类(协变返回类型)
  • 抛出异常小于等于父类
  • 访问权限大于等于父类

@Override注解可强制编译器检查重写是否正确,是最佳实践。

三、super 关键字:连接父类的桥梁

super关键字用于访问父类的成员,主要有三种用法:

  1. 调用父类构造器:
    public class GraduateStudent extends Student {
        private String researchDirection;
        
        public GraduateStudent(String name, int age, String studentId, 
                              String major, String researchDirection) {
            super(name, age, studentId, major); // 必须是子类构造器第一句
            this.researchDirection = researchDirection;
        }
    }
  2. 调用父类方法:

    @Override
    public void study() {
        super.study(); // 调用父类的study方法
        System.out.println("同时进行" + researchDirection + "研究");
    }

  3. 访问父类属性:

    public class Child extends Parent {
        private String name;
        
        public void printNames() {
            System.out.println("子类name: " + this.name);
            System.out.println("父类name: " + super.name);
        }
    }

    四、final 关键字与继承控制

final关键字可限制继承行为:

  1. final 类:不能被继承
    public final class String {
        // 源码不能被继承
    }

  2. final 方法:不能被重写
    public class Parent {
        public final void criticalOperation() {
            // 核心逻辑,不允许子类修改
        }
    }

  3. final 变量:继承中保持不变
    public class Constants {
        public static final double PI = 3.1415926;
    }

    五、实战案例:构建员工管理系统

// 顶层抽象类
public abstract class Employee {
    private String id;
    private String name;
    
    public Employee(String id, String name) {
        this.id = id;
        this.name = name;
    }
    
    public abstract double calculateSalary(); // 抽象方法
    
    // 共性方法
    public void printInfo() {
        System.out.println("员工ID: " + id + ", 姓名: " + name);
    }
}

// 全职员工
public class FullTimeEmployee extends Employee {
    private double monthlySalary;
    
    public FullTimeEmployee(String id, String name, double monthlySalary) {
        super(id, name);
        this.monthlySalary = monthlySalary;
    }
    
    @Override
    public double calculateSalary() {
        return monthlySalary;
    }
}

// 兼职员工
public class PartTimeEmployee extends Employee {
    private double hourlyRate;
    private int hoursWorked;
    
    public PartTimeEmployee(String id, String name, double hourlyRate, int hoursWorked) {
        super(id, name);
        this.hourlyRate = hourlyRate;
        this.hoursWorked = hoursWorked;
    }
    
    @Override
    public double calculateSalary() {
        return hourlyRate * hoursWorked;
    }
}

// 使用示例
public class EmployeeManager {
    public static void main(String[] args) {
        Employee ftEmp = new FullTimeEmployee("1001", "张三", 8000);
        Employee ptEmp = new PartTimeEmployee("2001", "李四", 50, 80);
        
        ftEmp.printInfo();
        System.out.println("月薪: " + ftEmp.calculateSalary());
        
        ptEmp.printInfo();
        System.out.println("时薪: " + ptEmp.calculateSalary());
    }
}

这个设计通过继承实现了员工类型的清晰划分,同时利用多态简化了薪资计算逻辑。

继承是 Java 中实现代码复用的强大机制,但也容易被滥用。优秀的继承设计应该满足:语义上的 is-a 关系、遵循合理的抽象层次。

思考:如何利用继承和多态设计一个图形绘制系统,支持圆形、矩形、三角形等多种图形的面积计算和绘制?欢迎在评论区分享你的思路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pretend________

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值