多重继承不好的观点是错误的 — 小评 松本行弘的程序世界

2023-10-05 13:30

本文主要是介绍多重继承不好的观点是错误的 — 小评 松本行弘的程序世界,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

首先得说, 一般某种语言的发明人写的关于自己语言的东西都是非常值得阅读的, 从别的牛人那里你也许能学会很多奇技淫巧, 但从语言发明人那里你能学到语言发明人本身设计的初衷, 以及设计时的一些抉择. 这种思路是独一无二, 绝无仅有的. 所以我在学习一个新语言时, 假如语言发明人有写书, 一定优先阅读.

语言发明人写的书又分两种, 一种是语言的教材, 这个几乎是惯例, 因为一个语言在初期, 没有其他人会用的时候, 语言发明人不教会别人怎么使用, 那可能就没有人会用了, 而他们这本教材的好坏甚至能决定他们语言最后能有多流行. 我听说一个有意思的言论, 说C语言之所以这样流行, 很重要的原因就是C程序设计语言这本教材实在写的太好了. 虽然有些夸张, 但是不无道理, 这个和现在一些开源库对文档要求很高的道理是一样的, 一个开源库的文档写的好不好, 对这个库最后是不是会被很多人使用有极大的关系. 当然, 也有反例, 鬼知道Anders Hejlsberg是怎么把一本C#的语言的教材C#程序设计语言, 写的就像是语言的规格说明书一样.
另外一种, 那就是除了教材外, 写关于自己语言的设计想法的书, 这种书就更加少了, 就目前而言, 我只看到过Bjarne Stroustrup写的C++语言的设计与演化和这本松本行弘的程序世界. 欢迎大家给我推荐其他的类似书籍. C++语言的设计与演化讲述了BS在设计C++时的各种抉择, 看完该书后, 我第一次明白C++到底是怎么设计成那么难用的, 当然, 同时也明白了怎么使用C++是正确的. 后来还反复的读了好几遍, 工作后, 也极力的推荐给使用C++的同事阅读, 事实上, 现在我买的这本书就还在我原来的同事那里, 虽然我已经离开原公司了. 如果说, 那个时候读C++语言的设计与演化还太无知(我那时候才刚刚参加工作), 并且C++又是我接触编程的第一门语言, 导致碰到一些可能习以为常的东西还如获至珍, 所以才这么喜欢的话, 那松本行弘的程序世界在我工作五年, 已经或多或少学习了不下于10门编程语言后, 仍然能给我很多启发, 就更加值得向大家推荐了.

  • Ruby的继承体系
    • Mix-in
      • Ruby的Stream结构
      • C++的Stream结构
  • 本书不足
  • 额外的声明

Ruby的继承体系

多重继承不好的观点是错误的
– 松本行弘

这是我感觉是全书最精彩的部分, 本文也主要关注这一部分. 特别是对于多重继承部分的描述, 充分体现了一个优秀的程序员, 语言设计者的功底.

讲到这里, 我想先讲讲我对这部分内容的认识历史.
在C++语言的设计与演化中, 我们知道, 多重继承在加入C++之前就有争议, 但是BS坚持自己的意见, 最终C++还是支持了多重继承. 并且为被很多人批评的多重继承进行了辩护, 他的确承认了多重继承可能带来的混乱, 但是认为, 在有的时候, 多重继承的抽象的确是有意义的, 并且这种抽象在有的时候会更加优美. 本着C/C++的设计原则, “程序员总是对的”, 不应该人为的去限制程序员, BS坚持的提供了多重继承这一工具, 并让程序员去决定, 什么时候用会导致混乱, 什么时候用可以让设计更加优美.
在成为标准以后, 多重继承的争议一直没有消失, 各种支持多种继承的语言甚至在怎么解决菱形继承上出现了不同的解决方案. 比如C++中, 菱形继承还引入了一个更扭曲的虚继承, Python支持多种继承, 并且因为所有的对象都继承于共同的基类Object, 导致任何多重继承其实都是菱形继承, 当你真的开始自己用多重继承时, 其实继承结构已经是一张网了, 对此, Guido Van Rossum的答案是用深度优先搜索, 靠基类排列的顺序来决定, 个人觉得不仅没有解决这个问题, 反而显的更加神奇.
而无数的JAVA用户者则是把C++的多重继承当作笑话和C++混乱的根源, 自豪的宣布JAVA没有这个问题. James Gosling给出了他自己的解决方案, 那就是没有没有C++自由的多重继承, 只支持对实现的单继承, 并引入了接口, 只允许接口的多重继承. 并且, 在继承接口和继承基类形式上特别加了一些区别, 所以实际中, 很多人并不把这叫做多重继承, 并宣称JAVA没有多重继承.
有意思的是, 高老头后来去了Google, 而我使用C++时尽量遵循的规范Google C++ Style Guide中就明确的规定了禁止C++的多种继承(不代表这两个事情有任何关系), 并且在Style Guide中自己给出了他们的Interface定义, 只允许使用此Interface进行类似JAVA的接口多重继承. 这真是趣事, 在一个Style Guide中, 去强行修改一个语言特性, 也足以证明C++的多重继承有多么臭名昭著了.

就个人感受, 以前开发的一个iOS游戏项目, 仅仅开发了半年, 就因为代码混乱不堪, bug多到无法维护, 项目一度在另外一个工作室被cancel, 然后我们中途再接手开发, 并且把多重继承看作是混乱的根源, 后来整理代码的很大部分工作就是用组件的方式去替代掉混乱的继承, 并且改善后设计清晰了很多, 再后来, 我开发一个Android项目的时候, 第一次真的在项目中去使用JAVA, 深刻的体会到了JAVA对继承的限制, 也真的去实践了GOF在设计模式中早就提到的”组合优于继承”这一设计原则, 也去体会了JAVA社区提倡的面向接口编程. 事实上, 我也逐渐的感觉到了, 其实, “继承本身就是一种强耦合”, 就是一种子类对父类的依赖耦合, 在一些书籍中提到, 甚至继承本身都是不提倡的, 也就是说, 提倡的是基于对象的设计(OB), 而不是面向对象的设计.(OO)

故事到这里就是我的认识了, 鉴于我的认识都来自于各种上述提到的流行语言和经典书籍, 我想大部分人可能会有和我类似的观点吧. 但是Mats不这么看.

Mix-in

本来只是为了跨越继承层次来共享代码, 现在却需要另外生成一个独立对象, 并且每次方法调用都要转送给那个对象, 这实在是不太合理, 而且执行的效率也不高.

Mats直说JAVA对多重继承的解决方式不够方便, 也不太合理. 他提供的解决方案是, Mix-in.
Mix-in按照以下规则来限制多重继承.
通常的继承用单一继承
第二个以及两个以上的父类必须是Mix-in的抽象类

Mix-in类是具有以下特征的抽象类.
不能单独生成实例
不能继承普通类

通过这种在接口和普通多重继承之间的折衷, Mix-in提供了对实现的多重继承, 同时对其进行了限制, 使得继承结构不会成菱形, 而是和单一继承一样的树型. 在Ruby中, Mix-in是通过模块(module)的概念来实现的. 作为例子, Matx用了Ruby中的Stream实现的例子.

Ruby的Stream结构

Ruby

C++的Stream结构

Cpp

从这点看, 为什么我说这是一种折衷方案呢, 因为相对于只允许接口的多重继承来说, 实现更加方便了, 但是, 对于真正的面向对象来说, 毕竟还是需要把一些实现给拆分成更细粒度的类, 才能符合Mix-in的要求. 比如看上面两个图就能发现, 同样的功能, C++需要的类要比Ruby需要的少. 从这点来说, Mats批评JAVA的组合方式为了共享代码需要生成一个独立对象是不方便的, 而实际上Max-in也会相对真正的多重继承来说需要更多的独立对象, 只是使用的方式不是组合, 而是继承. 当然, 这种限制能带来类似JAVA的更加良好的设计, 避免菱形继承及类似更加复杂的继承体系, 同时, 又比JAVA那种方式更加方便, 大家都知道, 加一个继承只要一个单词, 而加一个对象的组合调用, 往往需要增加N个函数接口, 以及N个调用.(虽然有种东西叫做委托) 有趣的事情是, 在编程这件事情上, 很多时候, 折衷的方法却往往是优秀的方法…

本书不足

  1. 作者在前言里面介绍, 是在杂志上连载的文章的基础上编辑修改来的, 所以有些地方其实能发现明显的重复, 甚至不仅仅是文字内容重复, 连Enumerable的那张表都原封不动的重复了两遍.
  2. 后面的章节趣味性有余, 但是感觉思想性稍微有些弱. 所以我看的时候过的比较快, 不过这也见仁见智吧, 也不排除我对相关内容兴趣不足的因素.

额外的声明

我在最新的文章中把所有关于书的链接从豆瓣改为亚马逊了, 假如你点击我的给的链接过去并且买了书, 亚马逊会给我一些佣金, 当然我知道这没有多少, 但是聊胜于无吧, 以后的文章类似, 不再声明了. 我甚至都不知道这样无害的事情为什么需要声明, 但是好像在中国你需要这样做, 因为别人都这么做了.

writen by  九天雁翎(www.jtianling.com)
           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow
这里写图片描述

这篇关于多重继承不好的观点是错误的 — 小评 松本行弘的程序世界的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/151300

相关文章

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

揭秘世界上那些同时横跨两大洲的国家

我们在《世界人口过亿的一级行政区分布》盘点全球是那些人口过亿的一级行政区。 现在我们介绍五个横跨两州的国家,并整理七大洲和这些国家的KML矢量数据分析分享给大家,如果你需要这些数据,请在文末查看领取方式。 世界上横跨两大洲的国家 地球被分为七个大洲分别是亚洲、欧洲、北美洲、南美洲、非洲、大洋洲和南极洲。 七大洲示意图 其中,南极洲是无人居住的大陆,而其他六个大洲则孕育了众多国家和

多重背包转换成0-1背包

http://acm.hdu.edu.cn/showproblem.php?pid=2191 多重背包特点: 一种物品有C个(既不是固定的1个,也不是无数个) 优化的方法: 运用神奇的二进制,进行物品拆分,转化成01背包 物品拆分,把13个相同的物品分成4组(1,2,4,6) 用这4组可以组成任意一个1~13之间的数! 原理:一个数总可以用2^

EMLOG程序单页友链和标签增加美化

单页友联效果图: 标签页面效果图: 源码介绍 EMLOG单页友情链接和TAG标签,友链单页文件代码main{width: 58%;是设置宽度 自己把设置成与您的网站宽度一样,如果自适应就填写100%,TAG文件不用修改 安装方法:把Links.php和tag.php上传到网站根目录即可,访问 域名/Links.php、域名/tag.php 所有模板适用,代码就不粘贴出来,已经打

跨系统环境下LabVIEW程序稳定运行

在LabVIEW开发中,不同电脑的配置和操作系统(如Win11与Win7)可能对程序的稳定运行产生影响。为了确保程序在不同平台上都能正常且稳定运行,需要从兼容性、驱动、以及性能优化等多个方面入手。本文将详细介绍如何在不同系统环境下,使LabVIEW开发的程序保持稳定运行的有效策略。 LabVIEW版本兼容性 LabVIEW各版本对不同操作系统的支持存在差异。因此,在开发程序时,尽量使用

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

JavaSE——封装、继承和多态

1. 封装 1.1 概念      面向对象程序三大特性:封装、继承、多态 。而类和对象阶段,主要研究的就是封装特性。何为封装呢?简单来说就是套壳屏蔽细节 。     比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器, USB 插孔等,让用户来和计算机进行交互,完成日常事务。但实际上:电脑真正工作的却是CPU 、显卡、内存等一些硬件元件。

这些心智程序你安装了吗?

原文题目:《为什么聪明人也会做蠢事(四)》 心智程序 大脑有两个特征导致人类不够理性,一个是处理信息方面的缺陷,一个是心智程序出了问题。前者可以称为“认知吝啬鬼”,前几篇文章已经讨论了。本期主要讲心智程序这个方面。 心智程序这一概念由哈佛大学认知科学家大卫•帕金斯提出,指个体可以从记忆中提取出的规则、知识、程序和策略,以辅助我们决策判断和解决问题。如果把人脑比喻成计算机,那心智程序就是人脑的

uniapp设置微信小程序的交互反馈

链接:uni.showToast(OBJECT) | uni-app官网 (dcloud.net.cn) 设置操作成功的弹窗: title是我们弹窗提示的文字 showToast是我们在加载的时候进入就会弹出的提示。 2.设置失败的提示窗口和标签 icon:'error'是设置我们失败的logo 设置的文字上限是7个文字,如果需要设置的提示文字过长就需要设置icon并给