面向对象程序设计大行其道几十年后,已经在面临淘汰?( 二 )


面向对象程序设计大行其道几十年后,已经在面临淘汰?文章插图
图源:unsplash
【面向对象程序设计大行其道几十年后,已经在面临淘汰?】脆弱的基类问题
如果已经成功地将另一个项目中的类重用于新代码 , 那么基类会发生怎样的变化?
它可能会破坏整个代码 , 而你甚至可能都没有碰过它 。 也许有一天你手上的项目熠熠生辉 , 而第二天却被打回原形 , 因为有人更改了基类中的一个细微细节 , 而该细节最终对项目至关重要 。
使用继承的次数越多 , 潜在的维护工作就越多 。 因此 , 即使在短期内重用代码似乎非常有效 , 但从长远来看 , 它可能会带来很大的代价 。
钻石问题
继承是一件可爱的小事 , 可以在其中继承一类的属性并将其转移给其他类 。 但该如何组合两个不同类的属性?
这也许做不到 , 至少没办法以简洁的方式做到 , 例如Copier类 。 (笔者从Charles Scalfani的热门文章《再见 , 面向对象的编程》中借用了这个示例以及有关此处出现的问题的一些信息 。 )复印机扫描文档的内容并将其打印在空白纸上 , 它应该是Scanner还是Printer的子类?
根本没有好的答案 。 即使这个问题不会破坏代码 , 但它经常出现足以令人沮丧 。
层次问题
在钻石问题中 , 问的是Copier是哪个类的子类 。 但其实我话没说完 , 有一个简单的解决方案 。 假设Copier 是父类 , 而Scanner 和Printer是仅继承属性子集的子类 。
这就变得很简单 。 但如果Copier只是黑白复印 , 而Printer还可以彩色打印怎么办?从这个意义上说 , 打印机不是包括复印机的吗?如果打印机连接到WiFi但复印机没有连接怎么办?
在类上堆积的属性越多 , 建立适当的层次结构就越困难 。 确实 , 在处理属性集群时 , 其中Copier共享了Printer的部分但不是全部属性 , 反之亦然 。 而且 , 如果尝试将其置于层次结构中 , 并且是一个大型复杂项目 , 则可能会导致混乱 。 不要混淆层次结构 , 否则可能会陷入混乱 。
面向对象程序设计大行其道几十年后,已经在面临淘汰?文章插图
图源:unsplash
参考问题
有人也许会说那么我们将进行没有层次结构的面向对象编程 。 其实相反 , 我们可以使用属性集群 , 并根据需要继承、扩展或覆盖属性 。 这会有些混乱 , 但这将是对当前问题的准确表现 。
还有一个问题 。 封装的全部目的是使数据片段彼此之间保持安全 , 从而使计算效率更高 。 没有严格的层次结构 , 这是行不通的 。
如果一个对象A通过与另一个对象B交互来覆盖层次结构 , 会发生什么?A与B的关系并不重要 , 除了B不是直接的父类 。 然后 , A必须包含对B的私有引用 , 否则 , 将无法交互 。 但是 , 如果A包含B的子代也具有的信息 , 则可以在多个位置修改该信息 。 因此 , 有关B的信息已不再安全 , 并且封装被破坏 。
尽管许多面向对象的程序员都使用这种架构来构建程序 , 但这并不是面向对象的编程 , 只是一团糟 。
面向对象程序设计大行其道几十年后,已经在面临淘汰?文章插图
单一范式的危险这五个问题的共同点是它们在不是最佳解决方案的地方实现了继承 。 由于继承甚至没有包含在面向对象编程的原始形式中 , 因此笔者不会将这些问题称为面向对象固有的问题 , 它们只是太过教条式的例子 。
但是 , 不仅面向对象的编程可能会被夸大 。 在纯函数式编程中 , 处理用户输入或在屏幕上打印消息极为困难 。 出于这些目的 , 面向对象或过程编程要好得多 。
仍然有一些开发人员尝试将这些东西实现为纯函数 , 并将其代码分解为数十行 , 没人能理解 。 使用另一种范式 , 他们可以轻松地将代码简化为几行可读的代码 。
范式有点像宗教 , 它们都具有一定的合理性 , 耶稣、穆罕默德和佛陀说了一些很酷的话 。 但是 , 如果一直遵循教条 , 可能最终会使自己和周围人的生活痛苦不堪 。 编程范式也是如此 。 毫无疑问 , 函数式编程正逐渐受到人们的欢迎 , 而在过去的几年中 , 面向对象的编程遭到了一些严厉的批评 。
了解新的编程范式并在适当的时候使用它们是有意义的 。 如果面向对象编程是使开发人员无论走到哪里都能看到钉子的锤子 , 那是把锤子扔出窗户的原因吗?不是 。 你在工具箱中添加了一把螺丝刀 , 也许是一把刀或一把剪刀 , 你不过是根据当前问题选择工具 。