一、继承的本质:消除冗余,构建逻辑关系

想象一个公司管理系统:普通销售员工(CommissionEmployee)和带底薪销售员工(BasePlusCommissionEmployee)共享大部分属性(姓名、工号、销售额、佣金率)。没有继承时,代码会变成这样:

// 普通销售员工类
class CommissionEmployee {private String name;private String identityNumber;private double grossSales;private double commissionRate;// 构造器和方法...
}// 带底薪销售员工类
class BasePlusCommissionEmployee {private String name;          // 重复private String identityNumber; // 重复private double grossSales;     // 重复private double commissionRate; // 重复private double baseSalary;     // 特有属性// 构造器和方法...
}

这种设计存在三大问题:

  1. 代码冗余:相同属性在多处重复
  2. 维护成本高:修改公共属性需同步所有类
  3. 关系缺失:未体现"带底薪员工也是销售员工"的逻辑

继承解决方案:

class CommissionEmployee { /* 公共属性 */ }
class BasePlusCommissionEmployee extends CommissionEmployee { private double baseSalary; // 仅定义特有属性
}

img


二、访问控制:protected与封装的艺术

继承中,子类如何访问父类属性?核心在于访问修饰符:

class Parent {private int x;    // 仅本类可访问protected int y;  // 子类可访问
}class Child extends Parent {void demo() {// System.out.println(x); // 错误!private不可访问System.out.println(y);   // 正确,protected允许访问}
}

最佳实践

class CommissionEmployee {private double grossSales; // 保持封装// 通过protected方法暴露访问protected double getGrossSales() { return grossSales; }
}class BasePlusCommissionEmployee extends CommissionEmployee {@Overridepublic double earnings() {// 通过getter安全访问父类属性return baseSalary + getGrossSales() * getCommissionRate();}
}

三、构造器:super()的初始化魔法

子类必须通过super()调用父类构造器,确保继承链完整:

class Employee {public Employee(String name, String id) {System.out.println("初始化员工基础信息");}
}class Manager extends Employee {private String department;public Manager(String name, String id, String dept) {super(name, id); // 必须第一行this.department = dept;System.out.println("添加经理专属属性");}
}

多级继承初始化顺序

class Person {public Person() { System.out.println("Person初始化"); }
}
class Employee extends Person {public Employee() { System.out.println("Employee初始化"); }
}
class Manager extends Employee {public Manager() { System.out.println("Manager初始化"); }
}
// 创建Manager时输出:
// Person初始化 → Employee初始化 → Manager初始化

四、方法重写:@Override的力量

当子类需要改变父类行为时,使用方法重写:

class Vehicle {public void startEngine() {System.out.println("启动普通引擎");}
}class ElectricCar extends Vehicle {@Overridepublic void startEngine() {System.out.println("静默启动电机"); // 完全重写}
}class HybridCar extends Vehicle {@Overridepublic void startEngine() {super.startEngine();       // 复用父类逻辑System.out.println("同时启动电机"); // 扩展新功能}
}

img

重写 vs 重载

// 重写(父子类间)
class Parent { void demo(int a) {} }
class Child extends Parent { @Override void demo(int a) {} // 相同签名
}// 重载(同一类内)
class Calculator {int add(int a, int b) { ... }      // 签名1double add(double a, double b) { ... } // 签名2
}

五、类层次设计:从Object到业务模型

所有Java类都隐式继承Object,可重写关键方法:

class Employee {private String name;@Overridepublic String toString() {return "员工: " + name; // 替换默认的类名@哈希值}
}

设计原则

  1. 单一职责:每层添加明确的新功能
  2. 层次扁平化:建议≤3层(如:Person→Employee→Manager)
  3. 组合优于继承:当"has-a"比"is-a"更合理时

六、实战:可运行的继承案例

// 基类(父类)
class MyParent {protected int x, y;  // 子类可访问的受保护属性public MyParent(int x, int y) {this.x = x;this.y = y;}public int getX() { return x; }public int getY() { return y; }
}// 派生类(子类)
class MyChild extends MyParent {public MyChild(int x, int y) {super(x, y);  // 必须调用父类构造器}// 子类特有方法public int calculateSum() {return x + y; // 直接访问父类protected属性}
}// 测试类
public class Main {public static void main(String[] args) {MyChild obj = new MyChild(5, 3);System.out.println("从父类继承的方法:");System.out.println("x = " + obj.getX()); // 输出: 5System.out.println("y = " + obj.getY()); // 输出: 3System.out.println("子类特有方法:");System.out.println("x+y = " + obj.calculateSum()); // 输出: 8}
}

执行结果

从父类继承的方法:
x = 5
y = 3
子类特有方法:
x+y = 8

七、继承的四大核心价值

代码复用

// 公共代码在父类写一次
class Animal {void breathe() { System.out.println("呼吸中..."); }
}
// 所有子类自动获得呼吸能力
class Fish extends Animal {}
class Bird extends Animal {}

多态支持

Animal[] zoo = {new Fish(), new Bird()};
for(Animal a : zoo) {a.breathe(); // 不同子类统一调用
}

扩展灵活

class Bird extends Animal {@Overridevoid breathe() {super.breathe();System.out.println("气囊辅助呼吸"); // 扩展功能}
}

系统可维护性

img


结语:明智使用继承

继承是把双刃剑,遵循三条黄金法则:

  1. 严格验证"is-a"关系(经理是员工✓,员工是公司✗)
  2. 优先用组合处理"has-a"关系(汽车有发动机→组合)
  3. 保持层次扁平(超过3层需重构)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/91438.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/91438.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/91438.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

工业数采引擎-DTU

DTU配置注册包及心跳包(对应设备配置->设备SN),模块工作方式:TcpClient,首次连接成功后,DTU发送上来的注册包作为链路SessionId1. ModbusRtu设备 -> Dtu -> Server2. DLT645设备 -> Dtu -> Server3. 自定义设备 -&…

AttributeError: ChatGLMTokenizer has no attribute vocab_size

请问运行下面语句tokenizer AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_codeTrue) 出现“AttributeError: ChatGLMTokenizer has no attribute vocab_size”是版本不一致,需要旧的版本卸载conda uninstall transformers或者pip un…

14.串口更新FLASH字库

一、简介 在使用STM32等单片机驱动显示屏时,为了显示中文字体,常用FLASH保存字库信息。但是字库的更新通常只能使用SD卡更新,在一些小型单片机系统(如STM32F103C8T6、STC89C52)上,没有增加SD卡支持的必要。为解决此问题&#xff0…

Lombok常用注解及功能详解

Lombok常用注解及功能详解一、Lombok简介与环境配置1.1 什么是Lombok?1.2 环境配置1.2.1 Maven项目1.2.2 Gradle项目1.2.3 IDE配置(关键)二、Lombok常用注解详解2.1 Data:一站式生成核心方法2.2 Getter/Setter:单独生成…

应用分层

应用分层是⼀种软件开发设计思想,它将应用程序分成N个层次,这N个层次分别负责各自的职责, 多个层次之间协同提供完整的功能。根据项目的复杂度,把项目分成三层,四层或者更多层。常见的MVC设计模式,就是应用…

[特殊字符] 【JAVA进阶】StringBuilder全方位解析:从使用到源码,一文搞定!

🔥 掌握StringBuilder,让你的Java字符串操作性能飙升!🧩 StringBuilder是什么? StringBuilder是Java中用于动态构建字符串的可变字符序列类,位于java.lang包中。与不可变的String类不同,StringB…

Redis 数据结构全景解析

Redis 不是简单的 key-value 缓存,它更像一把“瑞士军刀”。 只要掌握数据结构,就能把同一份内存用出 10 倍效率。0. 开场白:为什么聊数据结构? 面试常问“Redis 有几种数据类型?”——很多人答 5 种(Strin…

ansible.cfg 配置文件的常见配置项及其说明

配置项说明默认值defaults默认配置部分inventory指定清单文件的位置,可以是文件路径、目录或动态清单脚本。/etc/ansible/hostsremote_user默认的远程用户roothost_key_checking是否启用主机密钥检查。设置为 False 跳过 SSH 主机密钥验证。Trueask_pass是否在执行时…

Effective C++ 条款15:在资源管理类中提供对原始资源的访问

Effective C 条款15:在资源管理类中提供对原始资源的访问核心思想:RAII类需要提供访问其封装原始资源的显式或隐式接口,以兼容需要直接操作资源的API,同时维持资源的安全管理。 ⚠️ 1. 原始资源访问的必要性 使用场景示例&#x…

Linux 进程管理与计划任务设置

Linux 进程管理与计划任务设置一、进程管理进程管理用于监控、控制系统中运行的程序(进程),包括查看进程状态、调整优先级、终止异常进程等。以下是核心命令及操作说明:1. 常用进程查看命令(1)ps&#xff1…

MYSQL数据库之索引

1、引入索引的问题在图书馆查找一本书的过程,可类比数据库查询场景。在一般软件系统中,对数据库操作以查询为主,数据量较大时,优化查询是关键,索引便是优化查询的重要手段 。2、索引是什么索引是一种特殊文件&#xff…

ArcGIS以及ArcGIS Pro如何去除在线地图制作者名单

问题:ArcGIS和ArcGIS Pro提供了许多在线地图服务,但是这些地图会自动生成制作者名单,如下图所示: 在线地图加载方式可参考:如何在ArcGIS和ArcGIS Pro中添加在线底图 这在出图时有时会造成图的部分信息遮挡或出图不美观…

InfluxDB 与 Golang 框架集成:Gin 实战指南(二)

四、实际应用案例4.1 案例背景某智能工厂部署了大量的物联网设备,如传感器、智能仪表等,用于实时监测生产线上设备的运行状态、环境参数(如温度、湿度)以及生产过程中的各项指标(如产量、次品率)。这些设备…

Linux系统磁盘未分配的空间释放并分配给 / 根目录的详细操作【openEuler系统】

选择 Fix 修正 GPT 表 输入 Fix 并按回车,parted 会自动: 扩展 GPT 表的 结束位置 到磁盘末尾。释放未被使用的空间(1048576000 个 512B 块,约 500GB)。 验证修正结果 修正后,再次运行: parted …

王道考研-数据结构-01

数据结构-01视频链接:https://www.bilibili.com/video/BV1b7411N798?spm_id_from333.788.videopod.sections&vd_source940d88d085dc79e5d2d1c6c13ec7caf7&p2 数据结构到底在学什么? 数据结构这门课他要学习的就是怎么用程序代码把现实世界的问题给信息化&…

k8s云原生rook-ceph pvc快照与恢复(上)

#作者:Unstopabler 文章目录前言部署rook-ceph on kubernets条件Ceph快照概述什么是PVC安装快照控制器和CRD1.安装crds资源2.安装控制器3.安装快照类前言 Rook 是一个开源的云原生存储编排器,为各种存储解决方案提供平台、框架和支持,以便与…

springcloud04——网关gateway、熔断器 sentinel

目录 注册中心 nacos | eurekaServer |zookeeper(dubbo) 配置中心 nacos | config Server 远程服务调用 httpClient | RestTemplate | OpenFeign 负载均衡服务 ribbon | loadbalancer 网关 zuul | gateway 熔断器 hystrix | sentinel 网关 sentinel 流控 压测工具 1…

XSS跨站脚本攻击详解

一、XSS攻击简介跨站脚本攻击的英文全称是Cross-Site Scripting,为了与CSS有所区别,因此缩写为“XSS”由于同源策略的存在,攻击者或者恶意网站的JavaScript代码没有办法直接获取用户在其它网站的信息,但是如果攻击者有办法把恶意的…

Linux /proc/目录详解

文章目录前言文件说明注意事项前言 在 Linux 系统中,/proc 目录是一个特殊的虚拟文件系统,它提供了对系统内核和进程的访问。/proc 目录中的文件和目录不是真实存在的,它们是在运行时由内核动态生成的,用于提供系统和进程的相关信…

北斗变形监测在地质灾害监测中的应用

内容概要 北斗形变监测系统在地质灾害监测领域发挥着核心作用,该系统基于北斗卫星导航技术,实现对地表变形的精确追踪。通过毫米级精度定位能力,北斗形变监测技术为滑坡等灾害提供关键数据支撑,尤其在偏远地区应用中,单…