当前位置: 首页 > 编程日记 > 正文

转载知乎上的一篇:“ 面向对象编程的弊端是什么?”

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

弊端是,没有人还记得面向对象原本要解决的问题是什么。

1、面向对象原本要解决什么(或者说有什么优良特性)
似乎很简单,但实际又很不简单:面向对象三要素封装、继承、多态

警告:事实上,从业界如此总结出这面向对象三要素的一刹那开始,就已经开始犯错了!)。

封装:封装的意义,在于明确标识出允许外部使用的所有成员函数和数据项,或者叫接口

有了封装,就可以明确区分内外,使得类实现者可以修改封装的东西而不影响部调用者;而外部调用者也可以知道自己不可以碰哪里。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。



继承+多态:继承和多态必须一起说。一旦割裂,就说明理解上已经误入歧途了。

先说继承:继承同时具有两种含义:其一是继承基类的方法,并做出自己的扩展——号称解决了代码重用问题;其二是声明某个子类兼容于某基类(或者说,接口上完全兼容于基类),外部调用者可无需关注其差别(内部机制会自动把请求派发[dispatch]到合适的逻辑)。

再说多态:基于对象所属类的不同,外部对同一个方法的调用,实际执行的逻辑不同。

很显然,多态实际上是依附于继承的第二种含义的。让它与封装、继承这两个概念并列,是不符合逻辑的。不假思索的就把它们当作可并列概念使用的人,显然是从一开始就被误导了。


实践中,继承的第一种含义(实现继承)意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。

继承的第二种含义非常重要。它又叫“接口继承”。
接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化


归一化使得外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,如果你需要,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。

归一化的实例:
a、一切对象都可以序列化/toString
b、一切UI对象都是个window,都可以响应窗口事件。

——必须注意,是一切(符合xx条件的)对象皆可以做什么,而不是“一切皆对象”。后者毫无意义。


显然,归一化可以大大简化使用者的处理逻辑:这和带兵打仗是类似的,班长需要知道每个战士的姓名/性格/特长,否则就不知道该派谁去对付对面山坡上的狙击手;而连长呢,只需知道自己手下哪个班/排擅长什么就行了,然后安排他们各自去守一段战线;到了师长/军长那里,他更关注战场形势的转变及预期……没有这种层层简化、而是必须直接指挥到每个人的话,累死军长都没法指挥哪怕只是一场形势明朗的冲突——光一个个打完电话就能把他累成哑巴。


软件设计同样。比如说,消息循环在派发消息时,只需知道所有UI对象都是个window,都可以响应窗口消息就足够了;它没必要知道每个UI对象究竟是什么——该对象自己知道收到消息该怎么做。

合理划分功能层级、适时砍掉不必要的繁杂信息,一层层向上提供简洁却又完备的信息/接口,高层模块才不会被累死——KISS是最难也是最优的软件设计方法,没有之一。



总结:面向对象的好处实际就这么两点。
一是通过封装明确定义了何谓接口、何谓接口内部实现、何谓接口的外部调用者,使得大家各司其职,不得越界;
二是通过继承+多态这种内置机制,在语言的层面支持归一化的设计,并使得内行可以从代码本身看到这个设计——但,注意仅仅只是支持归一化的设计。不懂如何做出这种设计的外行仍然不可能从瞎胡闹的设计中得到任何好处。


显然,不用面向对象语言、不用class,一样可以做归一化的设计(如老掉牙的泛文件概念、游戏行业的一切皆精灵),一样可以封装(通过定义模块和接口),只是用面向对象语言可以直接用语言元素显式声明这些而已;
而用了面向对象语言,满篇都是class,并不等于就有了归一化的设计。甚至,因为被这些花哨的东西迷惑,反而更加不知道什么才是设计。


2、人们以为面向对象是什么、以及因此制造出的悲剧以及闹剧

误解一、面向对象语言支持用语言元素直接声明封装性和接口兼容性,所以用面向对象语言写出来的东西一定更清晰、易懂

事实上,既然class意味着声明了封装、继承意味着声明了接口兼容,那么错误的类设计显然就是错误的声明、盲目定义的类就是无意义的喋喋不休。而错误的声明比没有声明更糟;通篇毫无意义的喋喋不休还不如错误的声明

除非你真正做出了漂亮的设计,然后用面向对象的语法把这个设计声明出来——仅仅声明真正有设计、真正需要人们注意的地方,而不是到处瞎叫唤——否则不可能得到任何好处。

一切皆对象实质上是在鼓励堆砌毫无意义的喋喋不休。大部分人——注意,不是个别人——甚至被这种无意义的喋喋不休搞出了神经质,以至于非要在喋喋不休中找出意义:没错,我说的就是设计模式驱动编程,以及如此理解面向对象编程



误解二、面向对象三要素是封装、继承、多态,所以只要是面向对象语言写的程序,就一定“继承”了语言的这三个优良特性

事实上,如前所述,封装、继承、多态只是语言层面对良好设计的支持,并不能导向良好的设计。
如果你的设计做不出真正的封装性、不懂得何谓归一化,那它用什么写出来都是垃圾。



误解三、把软件写成面向对象的至少是无害的

要了解事实上是什么,需要先科普几个概念。

什么是真正的封装

——回答我,封装是不是等于“把不想让别人看到、以后可能修改的东西用private隐藏起来”?

显然不是
如果功能得不到满足、或者未曾预料到真正发生的需求变更,那么你怎么把一个成员变量/函数放到private里面的,将来就必须怎么把它挪出来。

你越瞎搞,越去搞某些华而不实的“灵活性”——比如某种设计模式——真正的需求来临时,你要动的地方就越多。

真正的封装是,经过深入的思考,做出良好的抽象,给出“完整且最小”的接口,并使得内部细节可以对外透明(注意:对外透明的意思是外部调用者可以顺利的得到自己想要的任何功能,完全意识不到内部细节的存在;而不是外部调用者为了完成某个功能、却被碍手碍脚的private声明弄得火冒三丈;最终只能通过怪异、复杂甚至奇葩的机制,才能更改他必须关注的细节——而且这种访问往往被实现的如此复杂,以至于稍不注意就会酿成大祸)。

一个设计,只有达到了这个高度,才能真正做到所谓的“封装性”,才能真正杜绝对内部细节的访问。

否则,生硬放进private里面的东西,最后还得生硬的被拖出来——当然,这种东西经常会被美化成“访问函数”之类渣渣(不是说访问函数是渣渣,而是说因为设计不良、不得不以访问函数之类玩意儿在封装上到处挖洞洞这种行为是渣渣)。



一个典型的例子,就是C++的new和过于灵活的内存使用方式之间的耦合。
这个耦合就导致了new[]/delete[]、placement new/placement delete之类怪异的东西:这些东西必须成对使用,怎么分配就必须怎么释放,任何错误搭配都可能导致程序崩溃——这是为了兼容C、以及得到更高执行效率的无奈之举;但,它更是“抽象层次过于复杂,以至于无法做出真正透明的设计”的典型案例:只能说,c++设计者是真正的大师,如此复杂的东西在他手里,才仅仅付出了如此之小的代价。

(更准确点说,是new/delete和c++的其它语言元素之间是非正交的;于是当同时使用这些语言元素时,就不可避免的出现了彼此扯淡的现象。即new/delete这个操作对其它语言元素非透明:在c++的设计里,是通过把new/delete分成两层,一是内存分配、二是在分配的内存上初始化,然后暴露这个分层细节,从而在最大程度上实现了封装——但比之其它真正能彼此透明的语言元素间的关系,new/delete显然过于复杂了)

这个案例,可以非常直观的说明“设计出真正对外透明的封装”究竟会有多难。





接口继承真正的好处是什么?是用了继承就显得比较高大上吗?

显然不是。

接口继承没有任何好处。它只是声明某些对象在某些场景下,可以用归一化的方式处理而已。

换句话说,如果不存在“需要不加区分的处理类似的一系列对象”的场合,那么继承不过是在装X罢了。



封装可应付需求变更、归一化可简化(类的使用者的)设计:以上,就是面向对象最最基本的好处。
——其它一切,都不过是在这两个基础上的衍生而已。


换言之,如果得不到这两个基本好处,那么也就没有任何衍生好处——应付需求变更/简化设计并不是打打嘴炮就能做到的。


了解了如上两点,那么,很显然:
1、如果你没有做出好的抽象、甚至完全不知道需要做好的抽象就忙着去“封装”,那么你只是在“封”和“装”而已。
这种“封”和“装”的行为只会制造累赘和虚假的承诺;这些累赘以及必然会变卦的承诺,必然会为未来的维护带来更多的麻烦,甚至拖垮整个项目。

正是这种累赘和虚假的承诺的拖累,而不是所谓的为了应付“需求改变”所必需的“灵活性”,才是大多数面向对象项目代码量暴增的元凶。

2、没有真正的抓到一类事物(在当前应用场景下)的根本,就去设计继承结构,是必不会有所得的。

不仅如此,请注意我强调了在当前应用场景下
这是因为,分类是一个极其主观的东西,不存在普适的分类法

举例来说,我要研究种族歧视,那么必然以肤色分类;换到法医学,那就按死因分类;生物学呢,则搞门科目属种……

想象下,需求是“时尚女装”,你却按“窒息死亡/溺水死亡/中毒死亡之体征”来了个分类……你说后面这软件还能写吗?



类似的,我遇到过写游戏的却去纠结“武器装备该不该从游戏角色继承”的神人。你觉得呢?

事实上,游戏界真正的抽象方法之一是:一切都是个有位置能感受时间流逝的精灵;而某个“感受到时间流逝显示不同图片的对象”,其实就是游戏主角;而“当收到碰撞事件时,改变主角下一轮显示的图片组的”,就是游戏逻辑。


看看它和“武器装备该不该从游戏角色继承”能差多远。想想到得后来,以游戏角色为基类的方案会变成什么样子?为什么会这样?





最具重量级的炸弹则是:正方形是不是一个矩形?它该不该从矩形继承?如果可以从矩形继承,那么什么是正方形的长和宽?在这个设计里,如果我修改了正方形的长,那么这个正方形类还能不能叫正方形?它不应该自然转换成长方形吗?什么语言能提供这种机制?

造成这颗炸弹的根本原因是,面向对象中的“类”,和我们日常语言乃至数学语言中的“类”根本就不是一码事。

面向对象中的“类”,意思是“接口上兼容的一系列对象”,关注的只不过是接口的兼容性而已(可搜索 里氏代换);关键放在“可一视同仁的处理”上(学术上叫is-a)。

显然,这个定义完全是且只是为了应付归一化的需要。

这个定义经常和我们日常对话中提到的类概念上重合;但,如前所述,根本上却彻彻底底是八杆子打不着的两码事。

就着生活经验滥用“类”这个术语,甚至依靠这种粗浅认识去做设计,必然会导致出现各种各样的偏差。这种设计实质上就是在胡说八道。
就着这种胡说八道来写程序——有人觉得这种人能有好结果吗?

——但,几乎所有的面向对象语言、差不多所有的面向对象方法论,却就是在鼓励大家都这么做,完全没有意识到它们的理论基础有多么的不牢靠。
——如此作死,焉能不死?!


——你还敢说面向对象无害吗?

——在真正明白何谓封装、何谓归一化之前,每一次写下class,就在错误的道路上又多走了一步。
——设计真正需要关注的核心其实很简单,就是封装和归一化。一个项目开始的时候,“class”写的越早,就离这个核心越远
——过去鼓吹的各种面向对象方法论、甚至某些语言本身,恰恰正是在怂恿甚至逼迫开发者尽可能早、尽可能多的写class。



误解四、只有面向对象语言写的程序才是面向对象的。

事实上,unix系统提出泛文件概念时,面向对象语言根本就不存在;游戏界的精灵这个基础抽象,最初是用C甚至汇编写的;……。

面向对象其实是汲取以上各种成功设计的经验才提出来的。

所以,面向对象的设计,不必非要c++/java之类支持面向对象的语言才能实现;它们不过是在你做出了面向对象的设计之后,能让你写得更惬意一些罢了——但,如果一个项目无需或无法做出面向对象的设计,某些面向对象语言反而会让你很难受。

用面向对象语言写程序,和一个程序的设计是面向对象的,两者是八杆子打不着的两码事。纯C写的linux kernel事实上比c++/java之类语言搞出来的大多数项目更加面向对象——只是绝大部分人都自以为自己到处瞎写class的面条代码才是面向对象的正统、而死脑筋的linus搞的泛文件抽象不过是过程式思维搞出来的老古董。

——这个误解之深,甚至达到连wiki词条里面,都把OOP定义为“用支持面向对象的语言写程序”的程度。
——恐怕这也是没有人说泛文件设计思想是个骗局、而面向对象却被业界大牛们严厉抨击的根本原因了:真正的封装、归一化精髓被抛弃,浮于表面的、喋喋不休的class/设计模式却成了”正统“!

借用楼下PeytonCai朋友的链接:
名家吐槽:面向对象编程从骨子里就有问题

————————————————————————————

总结: 面向对象其实是对过去成功的设计经验的总结。但那些成功的设计,不是因为用了封装/归一化而成功,而是切合自己面对的问题,给出了恰到好处的设计

让一个初学者知道自己应该向封装/归一化这个方向前进,是好的;用一个面向对象的条条框框把他们框在里面、甚至使得他们以为写下class是完全无需思索的、真正应该追求的是设计模式,则是罪恶的。

事实上,class写的越随意,才越需要设计模式;就着错误的实现写得越多、特性用得越多,它就越发的死板,以至于必须更加多得多的特性、模式、甚至语法hack,才能勉强完成需求。

只有经过真正的深思熟虑,才有可能做到KISS。


到处鼓噪的面向对象编程的最大弊端,是把软件设计工作偷换概念,变成了“就着class及相关教条瞎胡闹,不管有没有好处先插一杠子”,甚至使得人们忘记去关注“抽象是否真正简化了面对的问题”。

一言以蔽之:没有银弹。任何寄希望于靠着某种“高大上”的技术——无论是面向对象、数据驱动、消息驱动还是lambda、协程等等等等——就能一劳永逸的使得任何现实问题“迎刃而解”的企图都是注定要失败的,都不过是外行的意淫而已;靠意淫来做设计,不掉沟里才怪。

想要做出KISS的方案,就必须对面对的问题有透彻的了解,有足够的经验和能力,并经过深思熟虑,这才能做出简洁的抽象:至于最终的抽象是面向对象的、面向过程的还是数据驱动/消息驱动的,甚至是大杂烩的,都是可能的。只要这个设计能做到最重要、也是最难的KISS,那它就是个好设计。

的确有成功的经验、正确/合理的方向:技术无罪,但,没有银弹。

转载于:https://my.oschina.net/since1986/blog/330011

相关文章:

Windows Azure 如何学习Azure

通过上一篇博文可以得知,Azure其实是个平台,上面跑的服务五花八门,可以相互分开使用,同时也可以相互结合。 那我们应该如何来学习Azure呢? 其实有很多种选择,正所谓条条大路通罗马, 官方的training kit 提…

最全面的Unity游戏开发指南视频教程 第2卷

最全面的Unity游戏开发指南视频教程 第2卷 流派:电子学习| MP4 |视频:h264,1280720 |音频:AAC,44.1 KHz 语言:英语中英文字幕(根据原英文字幕机译更准确)|大小解压后:4.2 GB |时长:9h 24m 含项目文件 Unity游戏开发…

IOS面试题(二)

50. 谈谈对Block 的理解?并写出一个使用Block执行UIVew动画? 答:Block是可以获取其他函数局部变量的匿名函数,其不但方便开发,并且可以大幅提高应用的执行效率(多核心CPU可直接处理Block指令) 1 2 3 4 5 [UIView transitionWithView:self.…

辽宁省计算机专业A类,辽宁省2008年中职升高职招生考试计算机专业综合试题

辽宁省2008年中职升高职招生考试计算机及应用专业综合课试卷第一部分 必答题(200分)一、单项选择题(在每小题的四个备选答案中,选出一个正确的答案。每小题4分,共44分)1、在数据通信中,将模拟信号变换为数字信号的过程称为A 编码 B解码 C解调…

MyBatis的插入后获得主键的方式

需求&#xff1a; 使用MyBatis往MySQL数据库中插入一条记录后&#xff0c;需要返回该条记录的自增主键值。 方法&#xff1a; 在mapper中指定keyProperty属性&#xff0c;示例如下&#xff1a; <insert id"insertUser" useGeneratedKeys"true" keyP…

JAVA 中 13 种锁的实现方式

分布式系统时代,线程并发,资源抢占,慢慢变得很重要。那么常见的锁都有哪些?

String的Intern()方法,详解字符串常量池!

字符串拼接最好使用StringBuilder调用append来拼接。使用加号“+”拼接,会new一个StringBuilder,并且在最后调用toString方法时还会new String()。内存中由于创建了较多的StringBuilder和String对象,还有一方面是内存占用,调用GC还会额外花费时间。所以,字符串拼接直接使用StringBuilder会大大提高性能,尤其是多个字符串拼接。

硬盘盘符双击无法打开,只能右键打开(解决方法)(转载)

开始---运行---cmd&#xff0c;例如D盘&#xff0c;就输入  D: dir /a &#xff08;没有参数A是看不到的&#xff0c;A是显示所有的意思&#xff09; 此时你会发现一个autorun.inf文件   attrib autorun.inf -s -h -r 去掉autorun.inf文件的系统、只读、隐藏属性&#xff0…

Unity 2021创建2D休闲点击器游戏视频教程

Unity 2021创建2D休闲点击器游戏视频教程 Learn how to create a 2D Idle Clicker Game in Unity 2021 了解如何在Unity 2021中创建2D闲置点击器游戏 MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xff0c;44.1 KHz&#xff0c;2 Ch 语言&#xff1a;英语中英文字幕&…

html实现pdf预览打印机,Pdf操作(HTML转PDF,PDF直接网页连接打印机)

Pdf导出的操作&#xff1a;引用TuesPechkin.dll和TuesPechkin.Wkhtmltox.AnyCPU.dll程序集&#xff0c;新建PDF静态类 PDFConverter&#xff0c;在web.config配置保存dir/// ///pdf转换/// public static classPdfConvert {/// ///staticDeploymentPath/// private static read…

CUDA编程遇到的问题

1、总喜欢在core 代码中&#xff0c;访问device memory。 然后排错很久&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 2、第一次cudaMalloc() 耗时很久 3、cudaMalloc对于大数据也耗时很久 4、一致内存使用错误&#xff0c;不知道为什么&#xff01;&#xff…

2022-2028年中国数字化档案加工行业市场深度分析及发展策略分析报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国数字化档案加工行业市场行业相关概述、中国数字化档案加工行业市场行业运行环境、分析了中…

eclipse打开处于无响应状态解决办法

eclipse打开后处于无响应状态&#xff0c;变没有了反映&#xff0c;并且cup占用率为0。应该是非正常关机导致eclipse工作区的文件状态错误导致。 解决方案&#xff1a;在工作区目录中&#xff0c;有一个.metadata目录&#xff0c;里面是工作区及各插件的信息&#xff0c;删除此…

Unity创建在线多人游戏视频教程

Unity创建在线多人游戏视频教程 Learn To Create An Online Multiplayer Game In Unity 学会在Unity中创建在线多人游戏 MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xff0c;44.1 KHz&#xff0c;2 Ch 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更…

《需求分析》读后感之二

项目的目标是系统的业务需求。在很多情况下&#xff0c;涉众可以清晰地表达出系统的业务需求&#xff0c;这时可以通过安排和涉众的面谈来明确项目的动机。但也有很多情况下&#xff0c;涉众无法表达他们的业务需求&#xff0c;或者表达的业务需求不够清晰。因此&#xff0c;要…

统计学 计算机论文,统计学专业论文范文

1实验教学软件选择 目前流行的统计软件有SAS、SPSS、Statistica、EViews、Excel等&#xff0c;但上述软件的特点和功能优势各不相同&#xff0c;所以要根据学生的专业特点和教学要求选用不同的统计软件或者软件组合。但是由于专业统计软...2019-09-061非统计专业统计学教学过程…

JVM年轻代,老年代,永久代详解​​​​​​​

秉承不重复造轮子的原则&#xff0c;查看印象笔记分享连接↓↓↓↓ 传送门&#xff1a;JVM年轻代&#xff0c;老年代&#xff0c;永久代详解 速读摘要 最近被问到了这个问题&#xff0c;解释的不是很清晰&#xff0c;有一些概念略微模糊&#xff0c;在此进行整理和记录&…

html中#include file的使用方法

有两个文件a.htm和b.htm&#xff0c;在同一文件夹下a.htm内容例如以下 <!-- #include file"b.htm" --> b.htm内容例如以下 今天&#xff1a;雨 31 ℃&#xff5e;26 ℃ <br />明天&#xff1a;雷阵雨 33 ℃&#xff5e;27 ℃ 直接在浏览器中打开a&#…

Linux服务之Samba服务篇

Samba服务 桑巴Smb是基于cs架构 作用&#xff1a;用于跨平台进行文件共享 优点&#xff1a;兼容性好&#xff0c;较为安全(具备身份验证&#xff09; 缺点&#xff1a;仅限内网环境使用 应用&#xff1a;一般在办公环境下使用 rz 也是一种可以在Windows和Linux操作系统之间进行…

ue4商城素材 Cyberpunk City / Recife Environment 赛博朋克城市场景

ue4商城素材 Cyberpunk City / Recife Environment 赛博朋克城市场景 ue4商城素材 Cyberpunk City / Recife Environment 赛博朋克城市场景 ue4商城素材 Cyberpunk City / Recife Environment 赛博朋克城市场景 Unreal Engine虚幻游戏引擎素材资源 Unreal Engine Marketplace …

微型计算机系统外文,微型计算机控系统(单片机控制系统) 毕业论文外文翻译.doc...

微型计算机控系统(单片机控制系统) 毕业论文外文翻译英语翻译Microcontroller reset is to make the CPU and other system features are in a defined initial state, and from this state to work, reset PC 0000H, the microcontroller from the first - a unit to take co…

应用于cookie

将封装好的cookie函数 使用好cookie JavaScript代码 var aAdocument.getElementsByTagName(a); //使用var indexgetCookie(page_index);if(index){tab(index);}for(var i0; i<aA.length; i){(function(index){aA[i].onclickfunction(){tab(index); //设置一个cookiese…

2022-2028年中国数字电视产业投资分析及前景预测报告(全卷)

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国数字电视行业市场行业相关概述、中国数字电视行业市场行业运行环境、分析了中国数字电视行…

分形之闵可夫斯基(Minkowski)

与上一篇文章分形之正方形折线相似&#xff0c;闵可夫斯基分形也是分形出正方体&#xff0c;不同之处是它分出了两个正方体。 核心代码: static void FractalMinkowski(const Vector3& vStart, const Vector3& vEnd, Vector3* pVertices) {Vector3 vSub vEnd - vStart…

文本框禁用后(readonly=readonly),光标置于文本框中按后退键,页面后退的解决方案...

//处理键盘事件 禁止后退键&#xff08;Backspace&#xff09;密码或单行、多行文本框除外function forbidBackSpace(e){var ev e || window.event;//获取event对象 var obj ev.target || ev.srcElement;//获取事件源 var t obj.type || obj.getAttribute(type);//获取事件源…

最全19000+国外AE模板合集包

最全19000国外AE模板合集包 此套模板 包含整理好的 2015-2021年6月 国外AE模板 19000多个 大小&#xff1a;3500G 模板已编号&#xff0c;含预览视频&#xff0c;方便预览和查找&#xff0c;&#xff08;少数模板无预览&#xff0c;少数模板只含预览图&#xff09; 云桥网络…

北大网络教育计算机作业,北大网络教育(计算机专业)网络基础作业答案.doc

北大网络教育(计算机专业)网络基础作业答案北大网络教育(计算机专业)计算机网络基础作业答案1.从逻辑结构上看&#xff0c;计算机和路由器分别属于资源子网和通信子网。2、 大型广域网常采用的拓扑结构是网络拓扑结构。3.常借用公用传输网络构建的网络类型是广域网。4. 简单地说…

什么是IOC为什么要使用IOC

概念&#xff1a; 作用&#xff1a; 结论&#xff1a;借助于“第三方”实现具有依赖关系的对象之间的解耦 在使用IOC之前的情况 如果有一个齿轮出了问题&#xff0c;就可能会影响到整个齿轮组的正常运 使用IOC之后 对象A获得依赖对象B的过程,由主动行为变为了被动行为&#xff…

垃圾回收之标记算法

前言 作为 Java 开发人员&#xff0c;其实是非常幸福的&#xff0c;因为 JVM 的存在&#xff0c;使得 Java 开发人员不需要像 C 或者 C开发人员那样需要手动申请内存、释放内存&#xff0c;这些资源申请、垃圾回收的操作&#xff0c;JVM 底层直接帮助我们全干了。 这为 Java 开…

将数组转换为字符串

$a1..10000 方法一&#xff1a; $a -join $null 方法二&#xff1a; -join $a 方法三&#xff08;效率次高&#xff09;&#xff1a; [string]::concat($a) 方法四&#xff08;效率最高&#xff0c;但写法麻烦&#xff09;&#xff1a; $sb New-Object System.Text.StringBuil…