“组合”优于“继承”

C++组合优于继承?如何用完美转发优雅地“继承“基类方法 本文探讨了组合优于继承原则在实际应用中的困境,并提出基于C++11的完美转发解决方案。传统组合方式面临两个问题:公开基类对象违反封装原则,或需为每个基类方法编写大量包装函数。文章通过定义Animal基类和Whale子类,展示如何利用可变参数模板、成员函数指针和std::forward实现通用转发器。该方案能自动适配基类的任意公有方法,保持参数原始类型(左值/右值),且无运行时开销。这种编译时多态技术既维护了封装性,又提供了接近继承的语法便利性,是现代C++实现组合模式的理想方案。 阅读详情

《极限编程》(Extreme programming)的指导原则之一是“只要能用,就做最简单的”。一个似乎需要继承的设计常常能够戏剧性地使用组合来代替而大简化,从而使其更加灵活。

因此,在考虑一个设计时,问问自己:“使用组合是不是更简单?这里真的需要继承吗?它能带来什么好处?”

继承和组合的比较:


    面向对象系统中功能复用的两种最常用技术是类继承和对象组合(object composition)。正
如我们已解释过的,类继承允许你根据其他类的实现来定义一个类的实现。这种通过生成子
类的复用通常被称为白箱复用(white-box reuse)。术语“白箱”是相对可视性而言:在继承方
式中,父类的内部细节对子类可见。


    对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象
来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复用
(black-box reuse),因为对象的内部细节是不可见的。对象只以“黑箱”的形式出现。
继承和组合各有优缺点。类继承是在编译时刻静态定义的,且可直接使用,因为程序设
计语言直接支持类继承。类继承可以较方便地改变被复用的实现。当一个子类重定义一些而
不是全部操作时,它也能影响它所继承的操作,只要在这些操作中调用了被重定义的操作。
但是类继承也有一些不足之处。首先,因为继承在编译时刻就定义了,所以无法在运行
时刻改变从父类继承的实现。更糟的是,父类通常至少定义了部分子类的具体表示。因为继
承对子类揭示了其父类的实现细节,所以继承常被认为“破坏了封装性” [ S n y 8 6 ]。子类中的
实现与它的父类有如此紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生
变化。

    当你需要复用子类时,实现上的依赖性就会产生一些问题。如果继承下来的实现不适合
解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最
终限制了复用性。一个可用的解决方法就是只继承抽象类,因为抽象类通常提供较少的实现。
对象组合是通过获得对其他对象的引用而在运行时刻动态定义的。组合要求对象遵守彼
此的接口约定,进而要求更仔细地定义接口,而这些接口并不妨碍你将一个对象和其他对象
一起使用。这还会产生良好的结果:因为对象只能通过接口访问,所以我们并不破坏封装
性;只要类型一致,运行时刻还可以用一个对象来替代另一个对象;更进一步,因为对象的
实现是基于接口写的,所以实现上存在较少的依赖关系。


    对象组合对系统设计还有另一个作用,即优先使用对象组合有助于你保持每个类被封装,
并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控
制的庞然大物。另一方面,基于对象组合的设计会有更多的对象 (而有较少的类),且系统的行
为将依赖于对象间的关系而不是被定义在某个类中。


这导出了我们的面向对象设计的第二个原则:
    优先使用对象组合,而不是类继承。

【React】“组合优于继承“原则在 React 中的实践:设计哲学、实现模式与工程价值 组合优于继承”(Composition over Inheritance)是软件工程领域的经典设计原则,在现代前端框架 React 中得到了系统性实践。本文从面向对象编程的范式对比出发,系统分析继承模式与组合模式的本质差异,并深入论证 React 组件模型、Props 传递机制与自定义 Hooks 如何具体体现组合思想。 阅读详情

相关推荐

Java代码复用策略:组合优于继承的实际案例

摘要:本文探讨了面向对象编程中"组合优于继承"的设计原则。通过对比继承与组合的特性,指出继承存在紧耦合、基类脆弱等问题,而组合则提供了更好的灵活性、松耦合和可测试性。以游戏角色设计为例,展示了组合方式如何更灵活地实现行为组合。性能对比表明组合虽略有开销但优势明显,且被策略模式、装饰器模式等广泛应用。结论表明,在大多数场景下组合是更优的设计选择。

记录学习的过程 1195

设计模式试题-答案

1、设计模式一般用来解决什么样的问题( a) A.同一问题的不同表相 B不同问题的同一表相 C.不同问题的不同表相 D.以上都不是2、下列属于面向对象基本原则的是( c ) A.继承 B.封装 C.里氏代换 D都不是3、Open-Close原则的含义是一个软件实体( a ) A.应当对扩展开放,对修改关闭. B.应当对修改开放,对扩展

sanjiaozhen的专栏 5万+

深度解析:如何通过“组合优于继承”构建高内聚低耦合的模块

继承通过定义父类和子类建立“是一个”的关系。耦合性强:子类与父类紧密绑定,父类的任何修改可能引发子类异常。扩展困难:继承关系通常是静态的,难以灵活调整。功能混乱:由于继承可能导致子类不必要地拥有父类的功能,违反单一职责原则。通过合理应用“组合优于继承”,开发者可以构建高内聚、低耦合的模块,从容应对复杂业务需求。在设计过程中,务必秉承简单优雅的原则,确保代码的可维护性。开放讨论您在使用继承与组合时遇到过哪些挑战?如何解决这些问题?面对不断变化的技术生态,您认为组合设计是否还有更多潜在应用?

铭渊老黄 106

为什么组合优先于继承

面向对象编程中,有一条非常经典的设计原则,那就是:组合优于继承,多用组合少用继承。同样地,在《阿里巴巴Java开发手册》中有一条规定:谨慎使用继承的方式进行扩展,优先使用组合的方式实现。 为什么不推荐使用继承 每个人在刚刚学习面向对象编程时都会觉得:继承可以实现类的复用。所以,很多开发人员在需要复用一些代码的时候会很自然的使用类的继承的方式,因为书上就是这么写的。继承是面向对象的四大特性之一,用来表示类之间的is-a关系,可以解决代码复用的问题。虽然继承有诸多作用,但继承层次过深、过复杂,也会影响到代码的

Hopefully Sky的博客 1万+

FreeRTOS任务调度实战:如何让STM32同时处理温湿度采集、OLED显示和云端通信

本文通过一个基于STM32的物联网终端项目,详细讲解了如何利用FreeRTOS实现多任务调度,同时处理温湿度采集、OLED显示和云端通信。文章深入探讨了任务规划、堆栈分配、信号量与消息队列等核心机制,并重点优化了ESP8266通信任务的非阻塞设计与稳定性,为构建响应迅速、运行可靠的嵌入式系统提供了实战指南。

weixin_29188043的博客 331

KiCad自动布线实战:FreeRouting插件安装与使用指南

在PCB设计流程中,布线环节往往占据大量重复性工作,尤其对于中小型双面板,成百上千条飞线的手动连接既繁琐又易出错。自动布线技术通过算法在给定设计规则和元件布局的基础上自动规划走线路径,能显著提升布线效率。FreeRouting作为一款开源自动布线器,与KiCad通过DSN/SES标准中间格式无缝配合,让工程师将精力集中于关键信号和布局优化,而将常规网络交给工具处理。本文从自动布线的原理与边界出发,讲解了FreeRouting的安装、DSN导出、参数设置、自动布线及结果回传的完整流程,并结合实际案例展示了在S

weixin_32025789的博客 277

软件设计原则之组合优于继承

“组合优于继承”是一个面向对象编程的设计原则,它建议我们在需要复用代码的时候,尽量使用组合(has-a)的方式,而不是继承(is-a)的方式。组合是指一个类包含另一个类的对象作为自己的属性,而继承是指一个类直接从另一个类派生出来,拥有其所有的属性和方法。

hpx666的博客 1944

STM32F103C8T6用官方bootloader实现IAP升级操作方法

在使用STM32F103C8T6单片机IAP功能时,可以自己写bootloader程序,也可以使用官方bootloader文件。下面说一下使用官方bootloader的使用方法。 首先下载官方bootloader文件 目前使用的是这个版本,打开文件夹,选择适合自己编译器的工程。 目前使用的是keil,所以打开MDK-ARM文件夹 打开IAP工程 打开后根据自己的单片机型号,对工程进行简单的修...

HXYDJ的博客 1万+

7、组合优于继承原则(Composite Reuse Principle)

concept 复用时要尽量使用关联关系,少用继承 在系统中应尽量多使用对象间的关联关系(包括组合关系和聚合关系),尽量少使用甚至不使用继承关系来达到复用已有对象的目的。(了解关联关系请移步至博客 详解类之间的关系) ...

动如参商 3153

苍穹外卖项目面试总结话术

美食速递这个项目最初是我参与制作的大创项目,是一款为中南学生提供校园外卖送至宿舍服务的软件,包含系统管理后台和小程序端两部分。其中系统管理后台主要提供给食堂内部员工使用,可以对食堂各个窗口、员工、订单、菜品等进行维护管理;小程序端可以在线浏览菜品、添加购物车、下单等,由学生兼职做跑腿送餐上门服务。这是个前后端分离的项目,我主要是负责后端的用户登录、员工管理,菜品管理,订单管理模块的编码实现。

qq_45195447的博客 1万+

AI时代,程序员何去何从?别慌,看完这篇你就明白了

AI时代程序员的发展方向 摘要:随着AI代码助手的普及,程序员行业面临变革。本文通过实际案例展示AI写代码的能力与局限:AI能生成基础功能代码(如RESTful API、数据处理脚本),但缺乏业务理解、系统设计和复杂逻辑处理能力。程序员的核心价值在于需求分析、架构设计、性能优化等高层能力。未来程序员应: 掌握AI工具提升效率 专注于创新和架构设计 培养业务理解能力 持续学习新技术 AI不会取代程序员,但会淘汰不会使用AI的程序员。建议开发者拥抱AI工具,将其作为助手而非威胁,聚焦高价值工作。

yunque_xianguang的博客 908

《设计模式》——组合优于继承原则

一、组合优于继承 通常我们都听说过组合优于继承原则,但是可能不太明白为什么要这样用?本篇文章就以不同的场景,来阐述继承在某些场景下的缺点,以及组合的巧妙之处。 二、代码示例 1、场景一 制作一个集合,要求统计该集合诞生以来,共添加过多少元素(不是统计集合当前数量,而是一共加过多少) 那么我们使用继承,很容易实现,如下代码: package cn.com.design.model.test.composite.supplement.a; import java.util.Collection; import

qq_39857987的博客 2014

新手小白如何学习编程

学习目标推荐第一门语言优势网站 / APP 开发(前端)JavaScript浏览器原生支持,能快速做出可视化效果后端 / 服务器 / 数据分析Python语法简洁像英语,库多、应用广(入门友好)游戏开发先用电竞入门,再转专业引擎硬件 / 嵌入式(比如单片机)C 语言贴近硬件,行业标准办公自动化(Excel / 文档处理)Python快速解决重复工作(比如批量改文件)👉新手首选推荐。

2501_94331842的博客 2232

【转】“组合”优于“继承”

转自:http://blog.youkuaiyun.com/batoom/article/details/6037520 《极限编程》(Extreme programming)的指导原则之一是“只要能用,就做最简单的”。一个似乎需要继承的设计常常能够戏剧性地使用组合来代替而大简化,从而使其更加灵活。 因此,在考虑一个设计时,问问自己:“使用组合是不是更简单?这里真的需要继承吗?它能带来什么好处?...

andy76123的博客 96

2025小红书爬虫还能活?破解x-s签名+动态Cookie,亲测爬1000条笔记零封禁(附逆向全过程)

上周帮美妆行业的朋友爬小红书“口红推荐”笔记,刚发30个请求就被403,抓包一看x-s签名不对;换Cookie继续爬,爬50条又被封——小红书的反爬这两年简直是“地狱模式”:动态Cookie每10分钟过期,x-s签名算法季度更新,连请求头的User-Agent顺序错了都会被拦。。这篇文章不藏私,把逆向x-s签名的全过程、动态Cookie的维护技巧、1000条稳定爬取的实战代码全给你,连我踩过的8个坑都标出来了(最后附代理池配置,IP零封禁的关键)。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 7405

【SCADA】KingSCADA将数据插入SQLServer的方法

1、创建数据库及数据表格;2、配置ODBC数据源。3、通过KingSCADA与数据库建立连接,将数据写入数据库对应表格。

做有价值的事,积累有价值的笔记! 4958

为什么 Laravel 越来越倾向于用 Trait 或接口 而非深层继承?这与“组合优于继承”原则有何关系?

原则Laravel 实践组合优于继承用 Trait 注入行为,用接口定义契约依赖倒置高层代码依赖接口,实现由容器注入单一职责每个 Trait/接口只做一件事开闭原则通过组合扩展功能,无需修改现有代码高内聚低耦合模块间通过接口交互,内部用 Trait 聚合能力🔚Laravel 的演进方向非常清晰“用 Trait 提供可选能力,用接口定义稳定契约,用服务容器实现运行时组合”。这种设计既保持了 Laravel “优雅 API”的易用性,又为复杂应用提供了企业级的架构弹性——

长风破浪会有时的博客 669

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

“组合优于继承”——经典案例,简单易懂

文字+代码+经典例子,通俗易懂

i_believe_you的博客 1048

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

由“为什么VO不能继承PO?” 引出的为什么组合优于继承?

我在个人项目中喜欢直接使用各种 `model` 来继承 `po`,单纯的因为可以直接省去写各种重复 `getter` 和 `setter` 的步骤,并且不需要使用各种拷贝工具。但是,搞`vo`、`do`、`po`,还有其他各种 `o`,是为了解藕它们之间的联系,而继承却是建立它们之间的耦合关系,确实是会限制类的扩展性和灵活性。

ShockChen7的博客 1429

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

“组合”优于“继承” 例子

组合 通过创建一个由其他对象组合的对象来获得新功能的重用方法新功能的获得是通过调用组合对象的功能实现的有时又叫聚合例如: 一个对象拥有或者对另外一个对象负责并且两个对象有相同的生命周期。(GOF)一个对象包含另一个对象集合被包含对象对其他对象是不可见的并且只能从包含它的对象中访问的特殊组合形式 组合的优缺点 优点 被包含对象通过包含他们的类来访问黑盒重用,因为被包含对

唯梦可寻 1008

你听说过“组合优于继承”的说法吗?

1、继承是一种多态工具,而不是一种代码复用的工具。继承的错误使用:有些开发者喜欢用继承的方式来实现代码复用,即使在没有多态关系的情况下。继承的正确使用:继承只能用在类之间有“父子”关系的情况下。2、不要仅仅为了代码复用而继承。组合的优势:使用组合实现代码复用,不会产生继承关系。继承的劣势:过度使用继承,一旦修改父类,会损坏所有的子类,因为子类和父类的紧耦合关系在编译时就产生了。3、不要仅仅为了多态...

我有明珠一颗的博客 1194

Go 语言为什么没有继承?一场关于“组合优于继承”的设计哲学深思

Go 语言没有继承,这不是功能的缺失,而是设计哲学的超越。通过组合和接口,Go 提供了一种更灵活、更可维护的代码组织方式。它摒弃了传统 OOP 中复杂的类型层次结构,转而拥抱简单、清晰的组件化设计。“Go 不是为了证明什么理论,而是为了解决实际问题。在云计算、微服务、高并发成为主流的今天,Go 的设计哲学显得愈发前瞻。有时候,少即是多。放弃一些“强大”的特性,反而能获得更大的自由。

白僧的博客 425

Unity游戏代码:常说“组合”优于“继承”,为什么、怎么写?

继承:“”的思维方式,组合:“”的设计方法。

foolbirdM的博客 402

「设计模式」设计模式7大原则-组合优于继承原则

设计模式原则:组合优于继承还有个专业术语称为:合成复用原则,他俩是一个意思。 组合优于继承你可以将它理解为:关联优于继承,为什么呢?先来看看类与类之间的关系 其中,关联又可细分为 组合、聚合,因此组合优于继承可以理解为关联优于继承。 组合优于继承原则不能说是必须遵守的,像后面介绍的设计模式中也有用继承来实现的,究竟要不要遵守还是要看业务的,从这点理解起来就感觉组合优于继承就很模棱两可,下面仅仅从继承与组合的特点上粗略的说说,对比思考可能更容易理解些: 对象继承: 继承关系在编译阶段就已经...

攻城狮 1007
上一篇: DSP 的数据类型,DSP支持long的长度是64位。
下一篇: C++编译期间类中的常量
batoom
博客等级 码龄20年 32粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值