为什么说组合优于继承?

在编程中,继承和组合是用于在面向对象语言中设计和构建类和对象的两种基本技术。

继承,它允许一个类(称为派生类或子类)从另一个类(称为基类或超类)继承属性和行为。换句话说,子类“是”超类的一种类型。它建立了一种“是”关系。例如,如果我们有一个类“Animal”和一个类“Dog”,则“Dog”类继承自“Animal”,因为狗是一种动物。

组合,涉及使用其他对象作为组件来构建对象。类不是继承属性和行为,而是使用其他类的实例来实现其功能。它建立了“有”关系。例如,“Car”类可以具有“Engine”类和“Wheel”类的组合。

优势劣势相关设计模式
继承(1)允许子类从超类继承属性和方法来促进代码重用。
(2)有助于在单个继承树下组织和抽象相关类。
(3)通过遵循清晰的层次结构来简化对类结构的理解。
(4)协助定义子类的通用接口和协定。
(5)通过在类结构中反映逻辑关系来增强代码的可读性。


(1)可能导致类之间的高度耦合,使代码更难维护和修改,超类中的修改可能会影响所有子类。
(2)随着时间的流逝,继承层次结构通常会变得复杂且难以管理,可能会增加代码复杂性,使类理解更具挑战性。
(3)添加新类可能需要对现有层次结构进行重大更改。
(4)如果访问限制管理不当,可能会引入安全问题。
(5)当创建大量子类实例时,可能会导致内存消耗过高。

工厂模式
组合(1)促进低耦合,通过允许通过合成组合和自定义对象来提供更大的灵活性。
(2)允许在不影响主类的情况下修改组件,从而简化更新。
(3)通过“有”关系,促进组件聚合复杂对象的创建。
(4)可以通过避免继承开销来提高性能和强耦合等继承问题。
(5)促进更加模块化和易于理解的代码结构。
(1)可能会导致创建由大量组件组成的对象,这些组件的维护可能很复杂。
(2)缺乏明确的阶级层次结构。
(3)在大型应用程序中,组件生命周期管理可能很复杂,需要更大的初始设计投资来定义适当的组合关系。
装饰者模式、策略模式

在面向对象编程中,组合通常被认为优于继承,这主要是因为组合提供了一种更为灵活和可维护的方式来构建和扩展类的功能。

代码复用与扩展性。 通过继承,子类可以自动获取父类的所有属性和方法,实现代码的复用。但这也可能导致类的层次结构变得复杂,增加代码维护的难度。同时,当父类发生改变时,子类可能也需要相应的调整。通过组合,一个类可以将其他类的对象作为自己的成员变量来使用,从而复用这些对象的功能。这种方式更为灵活,因为被组合的类(成员变量)可以独立地改变和扩展,而不需要修改包含它们的类。

降低类之间的耦合度。 在继承关系中,子类与父类之间存在紧密的耦合关系,子类对父类的任何修改都可能产生影响。通过组合,类之间的关系更为松散,一个类的改变通常不会影响到其他类,除非它们共享相同的成员变量。

以汽车和发动机为例。如果我们使用继承来表示汽车和发动机的关系,可能会定义一个“汽车”类,然后定义一个“电动汽车”类继承自“汽车”类,并添加与电池和电机相关的属性和方法。但这种设计可能导致层次结构复杂,且不易于扩展其他类型的汽车(如混合动力汽车)。相反,我们可以通过组合关系,定义一个“汽车”类,它包含一个“发动机”对象作为成员变量。然后,我们可以定义不同类型的发动机类(如汽油发动机、柴油发动机、电动机等),并将它们作为参数传递给“汽车”类的构造函数。这样,我们可以轻松地创建不同类型的汽车,而无需修改“汽车”类本身。此外,我们还可以独立地测试“汽车”类和各种“发动机”类。

为什么Go、Rust等新兴语言舍弃了继承特性

Go和Rust等新兴语言选择不直接支持传统面向对象编程(OOP)中的继承特性,而是采用了其他机制来实现代码复用和扩展性,这主要是基于以下几个原因:

简洁性:Go和Rust的设计目标之一就是保持语言的简洁性。传统面向对象编程中的继承机制往往会引入复杂的层级结构和方法重写规则,增加了代码的复杂性。为了保持语言的简洁和易读性,Go和Rust选择了更简单的代码复用机制,如组合(composition)和接口(interface)。

灵活性:继承机制在编译时确定了类的结构,这限制了代码的灵活性和可适应性。而组合允许对象动态地获取、替换、增加或删除其行为,使代码更加灵活和可扩展。Go和Rust通过接口和trait提供了类似的功能,允许开发者以更灵活的方式组织代码。

正交性:继承机制通常与类、对象、封装等其他OOP特性紧密相关,这可能导致设计上的耦合和限制。Go和Rust更倾向于保持语言特性的正交性,即每个特性都可以独立使用,而不需要依赖于其他特性。因此,它们选择了更加独立的机制来实现代码复用和扩展性。

避免过度使用继承:在实践中,过度使用继承可能导致类层级过深、功能耦合紧密、代码难以维护等问题。Go和Rust的设计者意识到这些问题,并希望通过提供更简单的代码复用机制来避免过度使用继承。它们鼓励开发者使用组合和接口/trait来实现代码复用,这有助于保持代码的清晰和可维护性。

编译时检查和内存安全:Rust特别关注编译时检查和内存安全。继承机制可能使得编译器难以在编译时检查类型和行为的一致性,从而增加了内存不安全的风险。Rust通过trait系统提供了类似继承的功能,但更加严格地要求类型的一致性,有助于编译器在编译时发现问题,保证程序的内存安全。

小总结

继承和组合之间的选择取决于软件设计的要求和目标。一般来说,建议尽可能使用组合,以避免强耦合。当需要建立明确的“是”关系和类层次结构时,继承很有用,但应谨慎使用,以避免长期设计问题。在许多情况下,继承和组合的平衡组合可能是最佳解决方案。

参考:

https://medium.com/@josueparra2892/comparing-inheritance-and-composition-b27c8f93299a

https://zhuanlan.zhihu.com/p/60282972

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/689984.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

防汛应急排涝泵车的特点,有哪些用途

一、产品概述 移动柴油水泵机组又称移动拖车泵,它采用柴油作为燃料,通过内燃机的工作原理将化学能转化为机械能,进而驱动水泵进行抽水或输送任务。这种机组广泛应用于消防、市政应急给水、农业灌溉、防洪抢险等多个领域,其灵活性…

Pyinstaller安装与使用

一、Pyinstaller简介 PyInstaller将Python应用程序冻结(打包)独立可执行文件中。它可以构建较小的可执行文件,它是完全多平台的,并且使用OS支持来加载动态库,从而确保完全兼容。 二、Pyinstaller安装 1、下载安装 首先安装“pip install pywin32” 其次“pip install …

从GPT-4提取关键特征:Extracting Concepts from GPT-4

大家好,我是木易,一个持续关注AI领域的互联网技术产品经理,国内Top2本科,美国Top10 CS研究生,MBA。我坚信AI是普通人变强的“外挂”,所以创建了“AI信息Gap”这个公众号,专注于分享AI全维度知识,包括但不限于AI科普,AI工具测评,AI效率提升,AI行业洞察。关注我,AI之…

Visual Studio 调试 Win32 出现 Task Manager / Explorer 无法打开,无法关机/重启

现象 Access is denied 无法关机 无法通过开始 -> 关机/重启 进行关机或者重启 无法打开新的应用 无法通过开始 -> 双击应用打开新的应用 已打开应用的使用不受影响 已经打开的应用可以正常操作 原因 杀毒软件;关掉杀毒软件就好了 问题查找过程 参考…

了解光伏储能技术的应用场景和优势

光伏发电是指利用太阳能电池板将太阳光转化为电能的过程。其优点在于清洁、高效、可再生,但光伏发电需要同时也存在间歇性和不稳定性问题。为了解决这一问题,光伏储能技术得到了广泛应用。其基本原理是将白天无法消耗的电能储存起来,以供需要…

海宁代理记账公司-专业的会计服务

随着中国经济的飞速发展,企业的规模和数量日益扩大,在这个过程中,如何保证企业的财务活动合规、准确无误地进行,成为了每个企业面临的重要问题,专业、可靠的代理记账公司应运而生。 海宁代理记账公司的主要职责就是为各…

无人机电机选型

2306的意思是电机定子直径23MM,定子高度6MM.在相同KV值的情况下电机的定子体积越大,扭矩越大:KV的意思是每增加1V的电压电机转速增加多少。同参数的电机KV越低,在低速的情况下能带动更大的质量。这也就解释了竞速机选用更高KV值的…

区块链的基本原理和优势

人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 目录 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌…

Gopherus工具的下载、使用

目录 概览 Gopherus工具的作用 Gopherus工具下载 Windows Linux Gopherus工具的使用帮助 Gopherus支持的Payload种类 总结 免责声明 本文所提供的文字和信息仅供学习和研究使用,请读者自觉遵守法律法规,不得利用本文所提供的信息从事任何违法活动…

计算机网络 —— 网络层(IP数据报)

计算机网络 —— 网络层(IP数据报) 网络层要满足的功能IP数据报IP数据报格式IP数据报首部格式数据部分 IP数据报分片 我们今天进入网络层的学习。 网络层要满足的功能 网络层作为OSI模型中的第三层,是计算机网络体系结构的关键组成部分&…

Android14 WMS-窗口绘制之relayoutWindow流程(一)-Client端

Android14 WMS-窗口添加流程(一)-Client端-CSDN博客 Android14 WMS-窗口添加流程(二)-Server端-CSDN博客 经过上述两个流程后,窗口的信息都已经传入了WMS端。 1. ViewRootImpl#setView 在窗口添加流程(一)中,有这个方法: http://aospxref…

通过无障碍控制 Compose 界面滚动的实战和原理剖析

前言 针对 Compose UI 工具包,开发者不仅需要掌握如何使用新的 UI 组件达到 design 需求,更需要了解和实现与 UI 的交互逻辑。 比如 touch 事件、Accessibility 事件等等。 Compose 中对 touch 事件的处理和原理,笔者已经在《通过调用栈快…

C# 集成 C++ 的方法和实践 - P/Invoke(平台调用)- 1

环境: 1 P/Invoke(平台调用): C#可以通过P/Invoke调用C编写的DLL中的函数。 1.1 适用范围: P/Invoke 是一种在 C# 程序中调用非托管代码(如 C 动态链接库)的方式。这种方法适用于函数调用相对…

[职场] 美术指导的重要作用 #学习方法#笔记

美术指导的重要作用 美术指导是广告、电影、电视剧等创意作品中的一个重要角色,负责整体视觉风格和美术设计的指导和管理。 美术指导的目标是通过视觉表达来传达故事的情感、氛围和主题,以及塑造角色和场景的形象。 美术指导在创作过程中扮演着重要的角…

基于Java Mq的数据交换平台实现_设计消息的格式和内容

基于Java Mq的数据交换平台实现 目录概述需求: 设计思路实现思路分析 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for change,challen…

前端UI框架Element Plus 和 Ant Design Vue哪个好

Element Plus 和 Ant Design Vue 都是基于 Vue.js 的 UI 组件库,它们具备一系列可复用的组件和丰富的功能,并且是当前国内主流的两个 UI 组件库。 (1)Element Plus 是饿了么前端团队推出的开源项目,是对 Element UI 的…

一文搞懂Python的异常

人生之事,不如意者十之有九。 在编程中亦是如此。异常(Exception),遍布于程序各个角落,开发工作的大部分coding,都是为了应对和解决它。 概念 异常,简而言之,是程序在执行期间发生的非预期的、非正常的事件或情况。 举个实际生活的例子: 你周末出门买大龙虾,但当你…

Docker 管理 | 代理配置、内网共享和 Harbor 部署

唠唠闲话 在现代软件开发和运维中,容器技术已经成为构建、部署和管理应用程序的标准工具。然而,在实际操作中,我们常常需要面对一些常见的挑战,如容器访问外部资源的代理配置、内网环境下的镜像共享以及企业级镜像管理。 本教程…

[linux] makefilegdb理解

目录 Linux项目自动化构建工具-make/Makefile 背景 理解 依赖关系 依赖方法 原理 Linux调试器-gdb使用 背景 开始使用 Linux项目自动化构建工具-make/Makefile 背景 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力 一个工…

问题:脾梗塞时,下列情况最符合的是 #职场发展#知识分享#媒体

问题:脾梗塞时,下列情况最符合的是 A、脾肿大 B、脾区摩擦感 C、两者均有 D、两者均无 参考答案如图所示