0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

面向对象编程会被抛弃吗?这5大问题不容忽视

电子设计 来源:电子设计 作者:电子设计 2020-10-30 12:03 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

20 世纪 60 年代,编程遇到了一个大问题:计算机还没有那么强大,需要以某种方式平衡数据结构和程序之间的能力。

这意味着,如果你有大量数据,那么不将计算机推向极限就无法充分利用这些数据。另外,如果你需要做很多事情,那么你就不能使用过多的数据,否则计算机将会一直运行下去。

接下来到了 1966、1967 年,Alan Kay 从理论上证明可以使用封装的微型计算机。这些微型计算机不共享数据,而是通过消息传递进行通信。这样就可以更加经济地使用计算资源。

尽管这个想法很巧妙,但直到 1981 年,面向对象编程才成为主流。在那之后,它就没有停止过吸引新的和经验丰富的软件开发者。面向对象的程序员市场一如既往地忙碌。

但是在最近几年中,这种已有几十年历史的编程范式受到越来越多的批评。难道是在面向对象编程大行其道 40 年之后,技术已经超越了这种范式?

函数和数据耦合

面向对象编程的主要思想非常简单:尝试将一个功能强大的程序整体分解为功能同样强大的多个部分。这样就可以将一些数据和那些只在相关数据上使用的函数耦合起来。

注意,这仅涵盖封装的概念。也就是说,位于对象内部的数据和函数对于外部是不可见的。我们只能通过消息(通常通过 getter 和 setter 函数)与对象的内容进行交互。

继承性和多态性并没有包含在最初的设计想法中,但是对于现在的面向对象编程而言是必需的。继承基本上意味着开发者可以定义具有其父类所有属性的子类。直到 1976 年,即面向对象的程序设计的概念问世十年之后,继承性才被引入。

又过了十年,多态性才进入面向对象的编程。简单来讲,这意味着某种方法或对象可以用做其他方法或对象的模板。从某种意义上说,多态性是继承性的泛化,因为并不是原始方法或对象的所有属性都需要传输到新实体。相反,你还可以选择重写一些属性。

多态性的特殊之处在于,即使两个实体在源代码中互相依赖,被调用实体的工作方式也更像插件。这使得开发人员的工作变得轻松,因为他们不必担心运行时的依赖关系。

值得一提的是,继承性和多态性并不是面向对象编程所特有的。真正的区别在于封装数据及其包含的方法。在计算资源比今天稀缺得多的时代,这是一个天才的想法。


面向对象编程中的 5 大问题

面向对象的编程一经问世,便改变了开发人员看待代码的方式。20 世纪 80 年代以前,过程式编程非常面向机器。开发人员需要非常了解计算机的工作原理才能编写好的代码。

通过封装数据和其他方法,面向对象的编程使软件开发更加以人为中心,符合人类的直觉。比如,方法 drive() 属于 car 数据组,而不是 teddybear 组。之后出现的继承性也很直观。比如,现代汽车(Hyundai)是汽车的一个子类,并且具有相同的属性,但 PooTheBear 不是,这样很好理解。

香蕉猴子丛林问题

想象一下,你正在设置一个新程序,并且正在考虑设计一个新类。然后,你回想起为另一个项目创建的简洁的小类,发现其对正在进行的工作很合适。

没问题,你可以将以前项目中的类在新项目中复用。

这里有一个问题:这个类可能是另一个类的子类,因此你需要将它的父类也包含在内。然后你会发现,这个父类可能也是另一个类的子类,以此类推,最后要面对一堆代码。

Erlang 的创建者 Joe Armstrong 曾有一句名言:「面向对象语言的问题在于,它们自带其自身周围的所有隐式环境。你想要香蕉,但是得到的却是拿着香蕉的大猩猩和整个丛林。」

这几乎可以说明一切。复用类是可以的,实际上这可能是面向对象编程的主要优点,但不要将其发挥到极致。有时你应该建立一个新的类,而不是添加大量依赖项。


脆弱的基类问题

想象一下,如果你已经成功地将另一个项目中的类复用于新的代码,那么如果基类发生变化会怎样?

这可能会破坏你整个新项目的代码,即使你可能什么也没做。一旦有人更改了基类中的一个细节,而这一点又对你的项目至关重要,那么这种影响将是非常大并且突然的。

使用继承的次数越多,潜在的维护工作就越多。因此,即使在短期内复用代码非常有效,但从长远来看,它可能让你付出一定的代价。

菱形继承问题

利用继承可以将一类中的属性传递给其他类。但是,如果你想混合两个不同类的属性怎么办?

没错,这无法完成,至少常规的方法都不行。以 Copier 类为例(在此引用以下链接文章中的例子:https://medium.com/@cscalfani/goodbye-object-oriented-programming-a59cda4c0e53),Copier 将扫描文件的内容并将其打印在白纸上。那么它应该是 Scanner 还是 Printer 的子类?

这个问题根本没有完美的答案。即使这个问题不会破坏你的代码,但它经常出现,会让人很沮丧。

层级问题

在菱形继承问题中,Copier 是哪个类的子类是问题的关键所在。但或许有个投机取巧的方案:假设 Copier 是父类,Scanner 和 Printer 是仅继承属性子集的子类,那么问题就解决了。

但如果你的 Copier 是黑白的,而 Printer 也能够处理彩色,那怎么办?从这个意义上说,Printer 不是 Copier 的一种泛化吗?如果 Printer 连接了 WiFi,而 Copier 没有呢?

类上堆积的属性越多,建立适当的层次结构就越困难。在你所处理的属性集群中,Copier 共享了 Printer 的一些属性,但不是全部属性,反之亦然。在大型复杂项目中,层次结构的问题会导致很大的混乱。


引用问题

你可能会想到进行没有层次结构的面向对象编程。我们可以使用属性集群,并根据需要继承、扩展或重写属性。也许这有点混乱,但这将是对当前问题的准确表示。

这里只存在一个问题:封装的全部目的是使数据片段彼此之间保持安全,从而使计算效率更高,但没有严格的层次结构,这是行不通的。

假设一个对象 A 通过与另一个对象 B 交互来覆盖层次结构,会发生什么情况?其他关系的情况并不重要,但当 B 不是 A 的直接父类时,A 必须包含 B 的全部私有引用,否则,它们将无法交互。

但是,如果 A 包含 B 的子类也具有的信息,那么就可以在多个位置修改该信息。因此,有关 B 的信息已经不再安全,并且封装已经被破坏。

尽管许多面向对象的程序员都使用这种架构来构建程序,但这并不是面向对象编程,只是一团糟。

单一范式存在的风险

以上 5 个问题的共同点是它们都存在不合适的继承。由于继承没有包含在面向对象编程的原始形式中,所以这些问题可能不能称为面向对象本身的问题。

但是也并不是只有面向对象编程会被夸大。在纯粹的函数式编程中,处理用户的输入或在屏幕上输出消息极其困难。对此,面向对象或面向过程编程会好很多。

但仍然有一些开发人员试图将这些东西用纯函数的方式实现,并且编写几十行没人能看懂的代码。而使用另一种范式就能够轻松地将代码简化为几行可读的代码。

毫无疑问,函数式编程正在得到更多关注,而面向对象编程近几年遭到一些诟病。了解新的编程范式并在适当的时候使用它们是很有意义的。无论哪种编程范式,都不需要只遵循一种,在适当的时候使用不同的编程范式才能更好地解决问题。

审核编辑 黄昊宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    借助边缘侧AI与数字预失真提升5G能效

    虽然5G已深刻改变世界,并兑现了高速率、低延迟、高密度连接的承诺,但也伴随着一项隐性代价:不容忽视的能耗成本。据爱立信预测,到本十年末,5G用户数量将达到67亿。然而,尽管5G的数据传
    的头像 发表于 11-20 16:45 1051次阅读
    借助边缘侧AI与数字预失真提升<b class='flag-5'>5</b>G能效

    UPS电源接市电时,过载问题不容忽视:一文读懂风险与应对策略

    在数字化时代,电力稳定性已成为保障企业生产、数据安全乃至日常生活的关键要素。UPS电源(不间断电源)作为电力保障的“最后一道防线”,其重要性不言而喻。然而,许多用户存在一个误区:认为UPS仅在市电中断时发挥作用,接市电时无需担心过载。实际上,UPS在接市电时同样可能因过载引发设备损坏、数据丢失甚至火灾等严重后果。本文将结合真实案例与技术原理,深度解析UPS过
    的头像 发表于 09-08 13:27 950次阅读
    UPS电源接市电时,过载问题<b class='flag-5'>不容忽视</b>:一文读懂风险与应对策略

    人工智能如何驱动碳化硅革命

    人工智能掀起的高算力浪潮中,算力中心日夜不息地运转,训练着庞大的模型,支撑着自动驾驶、科学发现和智能体机器人技术的快速发展。然而,辉煌算力背后却藏着不容忽视的“能量焦虑”--急剧增长的电力消耗与转换效率瓶颈。传统硅基功率器件这只能量转换的“老旧心脏”,在高频、高温的极限
    的头像 发表于 08-20 16:43 1126次阅读
    人工智能如何驱动碳化硅革命

    不良瓷嘴导致LED断线死灯问题多,瓷嘴优化刻不容

    在LED封装领域,焊线工艺是确保器件性能与可靠性的核心环节。而瓷嘴,作为焊线工艺中一个看似微小却极为关键的部件,其对引线键合品质的影响不容忽视。大量失效分析案例证明,LED封装器件的死灯失效绝大多数
    的头像 发表于 06-12 14:03 587次阅读
    不良瓷嘴导致LED断线死灯问题多,瓷嘴优化刻<b class='flag-5'>不容</b>缓

    FLIR Si2x防爆声学成像仪为工业安全保驾护航

    粉尘爆炸是工业环境中不容忽视的重大安全隐患,尤其在ATEX 22区,其潜在威胁不容忽视。为了有效应对这一挑战,FLIR Si2x声学成像仪应运而生。它能够精确检测压缩空气泄漏与机械故障的声音信号,帮助我们及时发现并处理潜在风险点,从而有效预防粉尘爆炸事故的发生,确保工业生
    的头像 发表于 05-23 14:40 655次阅读

    完整版—单片机编程思想(推荐下载!)

    第3章直接针对我们在实际工作中经常遇到的问题——多定时器、多延时器问题进行多线程编程实现,并在实现过程中引入消息处理机制。通过前3章的技术准备,在第4章正式提出面向对象编程思路。第
    发表于 04-16 15:06

    海康威视推出智能交通非机动车管控系列产品

    道路千万条,安全第一条,根据公安部道路交通安全研究中心数据,电动自行车肇事导致的交通事故在城市道路交通事故总量中约占10%,不戴头盔等行为的后果严重,不容忽视
    的头像 发表于 04-07 16:18 886次阅读

    海瑞思推出手持VOCs检测仪HV-1001

    在现代生产生活中,挥发性有机化合物(VOCs)的危害不容忽视。这些物质不仅对人体健康具有潜在威胁,还可能对环境造成污染。
    的头像 发表于 03-18 15:50 625次阅读

    如何通过电源滤波器的优化设计来降低其自身的能耗?

    电源滤波器是电子设备稳定运行的重要组件,但其自身能耗问题不容忽视。通过选择低损耗的电感和电容,优化散热设计和布局,可以显著降低元件的损耗。此外,合理调整参数也有助于降低能耗。
    的头像 发表于 03-16 16:53 556次阅读
    如何通过电源滤波器的优化设计来降低其自身的能耗?

    微型导轨在半导体设备中如何防止磨损?

    微型导轨在半导体设备中承载着执行精确定位运动控制的重任,其磨损问题不容忽视
    的头像 发表于 02-06 18:01 668次阅读
    微型导轨在半导体设备中如何防止磨损?

    英飞凌推出全新400V CoolSiC MOSFET系列

    随着人工智能(AI)技术的迅猛发展,为AI处理器提供高效、可靠的电源供应,成为了一个不容忽视的挑战。想要应对这一挑战,打造新一代功率器件是关键的一环。
    的头像 发表于 02-06 13:35 925次阅读

    为安全生产保驾护航 KMWIS无线智能传感器助力上海汇众汽车制造有限公司产线上振动日常巡检!

    ,设备产生振动异常往往是一个不容忽视的信号,它可能预示着潜在的设备故障或性能下降。一旦发现振动异常,应立即采取行动,以免小问题演变成大问题,影响生产线的正常运转。
    的头像 发表于 01-17 10:57 611次阅读
    为安全生产保驾护航 KMWIS无线智能传感器助力上海汇众汽车制造有限公司产线上振动日常巡检!

    EE-355:面向SHARC处理器的专家在线闪存编程

    电子发烧友网站提供《EE-355:面向SHARC处理器的专家在线闪存编程器.pdf》资料免费下载
    发表于 01-08 15:05 0次下载
    EE-355:<b class='flag-5'>面向</b>SHARC处理器的专家在线闪存<b class='flag-5'>编程</b>器

    物联网数据采集设备安全:警惕看不见的威胁

    物联网数据采集设备是数字化时代不可或缺的关键基石,它们在生活中的应用日益广泛,从健康生活、出行安全到工厂生产,无处不在。然而,网络安全威胁也不容忽视,防不胜防。
    的头像 发表于 01-06 10:13 706次阅读
    物联网数据采集设备安全:警惕看不见的威胁

    gitee 支持的编程语言有哪些

    Gitee 支持的常见编程语言: Python :一种广泛使用的高级编程语言,以其清晰的语法和代码可读性而闻名。 Java :一种面向对象编程
    的头像 发表于 01-06 09:50 1105次阅读