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

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

相关文章

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO

Python中ModuleNotFoundError: No module named ‘timm’的错误解决

《Python中ModuleNotFoundError:Nomodulenamed‘timm’的错误解决》本文主要介绍了Python中ModuleNotFoundError:Nomodulen... 目录一、引言二、错误原因分析三、解决办法1.安装timm模块2. 检查python环境3. 解决安装路径问题

如何解决mysql出现Incorrect string value for column ‘表项‘ at row 1错误问题

《如何解决mysql出现Incorrectstringvalueforcolumn‘表项‘atrow1错误问题》:本文主要介绍如何解决mysql出现Incorrectstringv... 目录mysql出现Incorrect string value for column ‘表项‘ at row 1错误报错

如何用java对接微信小程序下单后的发货接口

《如何用java对接微信小程序下单后的发货接口》:本文主要介绍在微信小程序后台实现发货通知的步骤,包括获取Access_token、使用RestTemplate调用发货接口、处理AccessTok... 目录配置参数 调用代码获取Access_token调用发货的接口类注意点总结配置参数 首先需要获取Ac

SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法

《SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法》本文主要介绍了SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法,具有一定的参考价值,感兴趣的可以了解一下... 目录方法1:更改IDE配置方法2:在Eclipse中清理项目方法3:使用Maven命令行在开发Sprin

基于Python开发PDF转Doc格式小程序

《基于Python开发PDF转Doc格式小程序》这篇文章主要为大家详细介绍了如何基于Python开发PDF转Doc格式小程序,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用python实现PDF转Doc格式小程序以下是一个使用Python实现PDF转DOC格式的GUI程序,采用T

前端bug调试的方法技巧及常见错误

《前端bug调试的方法技巧及常见错误》:本文主要介绍编程中常见的报错和Bug,以及调试的重要性,调试的基本流程是通过缩小范围来定位问题,并给出了推测法、删除代码法、console调试和debugg... 目录调试基本流程调试方法排查bug的两大技巧如何看控制台报错前端常见错误取值调用报错资源引入错误解析错误

将java程序打包成可执行文件的实现方式

《将java程序打包成可执行文件的实现方式》本文介绍了将Java程序打包成可执行文件的三种方法:手动打包(将编译后的代码及JRE运行环境一起打包),使用第三方打包工具(如Launch4j)和JDK自带... 目录1.问题提出2.如何将Java程序打包成可执行文件2.1将编译后的代码及jre运行环境一起打包2

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

在MySQL执行UPDATE语句时遇到的错误1175的解决方案

《在MySQL执行UPDATE语句时遇到的错误1175的解决方案》MySQL安全更新模式(SafeUpdateMode)限制了UPDATE和DELETE操作,要求使用WHERE子句时必须基于主键或索引... mysql 中遇到的 Error Code: 1175 是由于启用了 安全更新模式(Safe Upd