当前位置: 首页 > news >正文

面向对象三大特性---继承

什么是继承

继承的概念来源于现实生活,维基百科将其定义为:在所有权人死亡后,将其财产、债务、爵位、世袭官职等转移给一个或多个继承人继承。而在Java编程语言中,继承是面向对象的三大特性之一。

继承的本质是代码复用,当我们发现多个类之间存在相同的属性或行为时,可以将这些共同特征抽取到一个父类中,然后让具体的子类去继承这个父类。比如,我们可以定义一个Animal类作为父类, 然后让Dog Cat等具体的动物类作为子类来继承它。

让我们用实际例子来理解继承的使用场景:

// 父类:动物类
public class Animal {protected String name;public Animal(String name) {this.name = name;}public void eat() {System.out.println(name + "正在吃东西");}
}// 子类:猫类
public class Cat extends Animal {public Cat(String name) {super(name);}
}

运行结果:

public class Demo {public static void main(String[] args) {Animal animal = new Animal("旺财");Cat cat = new Cat("咪咪");animal.eat();      // 输出:旺财正在吃东西cat.eat();         // 输出:咪咪正在吃东西}
}

我们可以观察到,虽然没有在cat类写任何的属性和方法,但依然可以使用父类的属性和方法

单继承与多继承

单继承

Java采用单继承机制,即一个子类只能有一个直接父类。这种设计避免了许多复杂的问题,使得类的层次结构更加清晰。在上面的例子中,Dog类和Cat类都只继承了Animal这一个父类。

多继承

一些编程语言(如C++)支持多继承,允许一个类同时继承多个父类。虽然这看起来更加灵活,但实际上会带来很多问题:

最典型的问题是菱形继承,假设我们有如下继承结构:

在这里插入图片描述
如果B和C都重写了A类的某个方法,那么D类继承这个方法时就会产生歧义:到底继承哪个父类的实现?俺不中嘞!

C++为了解决这个问题引入了虚继承,但这又增加了语言的复杂性。Java的设计者认为,既然多继承的使用场景相对较少,而带来的问题却很多,不如采用更简洁的单继承模式。

接口:多继承的替代方案

Java通过接口可以弥补单继承的不足。接口定义了一组方法签名,类可以实现多个接口,从而获得类似多继承的效果,但又避免了菱形继承的问题。

// 接口定义
public interface Flyable {void fly();
}public interface Swimmable {void swim();
}// 实现多个接口
public class Duck extends Animal implements Flyable, Swimmable {public Duck(String name, int age) {super(name, age);}@Overridepublic void fly() {System.out.println(name + "正在飞翔");}@Overridepublic void swim() {System.out.println(name + "正在游泳");}
}

继承的优缺点分析

优点

  1. 代码复用:子类可以继承父类的属性和方法,减少重复代码的编写。
  2. 扩展性:可以在不修改原有代码的基础上,通过继承来扩展功能。
  3. 多态性基础:继承为多态提供了基础,使得程序更加灵活。
  4. 代码组织:通过继承可以建立清晰的类层次结构,便于理解和维护。

缺点

  1. 耦合度增加:子类与父类之间存在强耦合关系,父类的变化会直接影响子类。
  2. 破坏封装性:子类需要了解父类的内部实现细节,违背了封装的原则。
  3. 维护困难:当父类发生变化时,所有子类都可能需要进行相应的修改,“牵一发而动全身”。
  4. 滥用风险:过度使用继承可能导致类层次过深,增加系统复杂性。

继承的最佳实践

  1. 遵循里氏替换原则:子类应该能够替换父类出现在程序中的任何地方,而不影响程序的正确性。
  2. **优先使用组合而非继承:**当类之间的关系是"has-a"而不是"is-a"时,应该使用组合而不是继承。
  3. 合理使用访问修饰符:
  • 使用protected修饰符来保护父类的内部实现
  • 谨慎使用public继承,避免暴露过多的实现细节
  1. **避免过深的继承层次:**一般建议继承层次不要超过3-4层,过深的继承层次会增加系统的复杂性和维护难度。

现代Java中的继承演进

Java 8的接口改进

从Java 8开始,接口可以包含默认方法(default method)和静态方法,这进一步增强了接口的功能,使其在某种程度上具备了多继承的特性:

public interface Drawable {void draw();// 默认方法default void print() {System.out.println("正在打印图形");}// 静态方法static void info() {System.out.println("这是一个可绘制接口");}
}

一句话总结

“把继承当成行为契约,而不是代码复用工具;子类签了契约,就必须能随时顶班。”

http://www.dtcms.com/a/286358.html

相关文章:

  • 大数据安全规划总体方案
  • 【深度学习】神经网络 批量标准化-part6
  • 在 OpenSUSE Tumbleweed 和 Leap 上安装 VirtualBox
  • Maven插件检测全路径名冲突如何开发Maven插件
  • AUTOSAR进阶图解==>AUTOSAR_SWS_E2ETransformer
  • 【加解密与C】Rot系列(二)Rot13
  • LVS(Linux virual server)
  • 【Git专栏】git如何切换到某个commit(超详细)
  • Java基础篇
  • Triton Inference Server 使用详解与常见问题汇总
  • 数据库模型异常问题深度解析:冗余与操作异常
  • 《在亚马逊平台运营:从专利困境到功能利用全指南》
  • 【数据结构】堆(下)+ 二叉树
  • 深度学习笔记002-引言--日常生活总的机器学习、训练模型的过程、关键组件、各种机器学习问题
  • 如何在服务器上获取Linux目录大小
  • 使用python读取json数据,简单的处理成元组数组
  • 验证大语言模型不会算数但可以编写算数的程序
  • 【数据结构初阶】--双向链表(一)
  • 机器学习17-Mamba
  • C语言—如何生成随机数+原理详细分析
  • Linux服务器端口被占用?
  • 无刷电机控制 - 基于STM32F405+CubeMX+HAL库+SimpleFOC04,完成霍尔传感器的驱动代码
  • @Scheduled的作用分析
  • 赛道观察:AI智能自习室哪家强?深挖深度逻辑与价值锚点
  • 链表算法之【链表的中间节点】
  • 【CMake】CMake 项目打包与 find_package 使用流程:从 A 到 B 的完整范例
  • 基于MATLAB的朴素贝叶斯NB的数据分类预测方法应用
  • 一种新颖的可解释人工智能框架,用于整合统计、视觉和基于规则的方法进行医学图像分类|文献速递-医学影像算法文献分享
  • Flutter ScaffoldMessenger 详细介绍
  • P1205 [USACO1.2] 方块转换 Transformations