厕所是如何建成的:胡侃面向对象基础

字体 -

厕所是如何建成的:胡侃面向对象基础

-叶雨

说真的,一直想给小朋友们写本教科书。因为我自己在小时候看见教科书特别害怕:不容易看懂。我感觉是似乎写教科书的老学究们觉得一定要用晦涩深奥的语言来写抖书包才算是有水平,要是通俗易懂,那就表示作者的水平低下,粗俗。

所以今天想跟立志入门IT的筒子们侃一下当下编程流行的面向对象的一些概念。

面向对象的概念在我们的现实生活中也是无处不在,所以今儿咱们不谈电脑,改拉家常。

那么既然说面向对象的概念无处不在,就举个例子吧:用我们如何解决“小便”这个问题,来谈谈面向对象的一些概念。

你的用户需求是这样的:我要小便,急。

为了解决这个艰巨的问题,叶雨来给你上堂课。我先问个问题:“你知道小便的方法有多少种吗?”(估计我会被茴香豆砸死)

好了,你首先要搞清楚,你小便需要什么?啥?厕所啊!你先忍着小便,听叶雨讲讲如何盖这个厕所。

我们要定义一下,什么是厕所。首先,厕所是个厕所,但同时它又不是个厕所。晕了吧?嗬嗬,这就是我要的效果。你要在挨踢(IT)界混,你要学会的第一件事情,就是“纸上谈兵”。

“纸上谈兵”这个事情,做得不好就是:“瞎掰”,做得好就叫“抽象设计”(Abstract)。所以具有“抽象”能力的挨踢人看到的厕所就不是厕所,而是能把一些共性抽取出来而形成一个“类”。

“类”(Class) 在这里就是建造厕所的蓝图。而“对象”(Object)就是用“厕所”的蓝图建造出来的实际“厕所”。现在懂了吧,为啥厕所(类)是个厕所(Class,蓝图),但同时它又不是个“厕所”(Object,实际建成的厕所实体)。

那么我们从厕所里除了能抽取粪便,还能抽取些什么出来?

至少我们有:马桶。这是构成所有厕所(中国旅游区的厕所除外)的基本要素。

好了,所以在我们的蓝图上,我们有:马桶。为了好听起见,这些东西称之为“属性”(Attribute)。当然,针对马桶可以有“解小便”这个动作,我们把这个动作称之为“方法”(Method)。好了,

现在出现一个面向对象的最重要的概念之一,就是“封装”(Encapsulation)。说白了就是“自成一体”。那么在“厕所”这个“类”里,封装了一个“属性”:马桶;也封装了一个“方法”:解小便。

“封装”真的太重要了。可以说没有它就不可能存在真正的“面向对象”。这么说吧:商店里在卖马桶,你能跑进去对着马桶就小便吗?最起码你得拿个什么把四周 围遮一下吧?你看,技巧就在这里。就这么“遮”一下,你就把马桶给“封装”成了一个“厕所”,从而可以自欺欺人地在里面舒畅。懂了吧?要是实在不懂就记住 祖国著名诗人赵丽华的诗:

“我坚决不能容忍 那些 在公共场所 随地大小便 的人。”

真搞不懂为啥这么多无聊的人在攻击赵丽华。人家小姑娘用一首小丝就道破了“封装”的重要性,难怪是国宝级的诗人,我们要好好保护才是。

说了这么多,忘了问一个重要问题,您要男厕所还是女厕所啊?完了吧,原以为你能“封装个”厕所赶紧让你解决问题,现在连男女厕所都没弄清!

还好,面向对象里面有“继承”(inheritance)功能。男厕所、女厕所,不都是厕所吗?所以它们能继承厕所“类”。因为男厕所和女厕所都继承了“厕所”,所以“厕所”成了父类(Super Class),男厕所和女厕所成了子类(Sub Class)。

“继承”是面向对象的第二个重要概念。

好了,既然继承了父类,我们盖男厕所的时候就已经具备了父类(厕所)的所有属性和方法。不过需要注意的是,在父类里面,“解小便”这个方法只被解释成“坐 着上”,没有考虑到有些变态男人也能“站着上”。于是乎男人为了自己的自私目的,重新定义男厕所里的“解小便”。这个方法的具体代码就是“坐着上还是站着 上,看我心情如何”。女厕所也继承了父类“厕所”的所有属性,她们老老实实地没有修改父类的“解小便”的具体代码,那就是维持“坐着上”(别跟我抬杠说女 人不一定要坐着,你就可怜可怜男人吧。现代社会女人已经无所不能,男人只剩下“站着上”这个最后专利了…..)

在子类各自解释不同的父类方法时,我们发现了第三个重要概念:“多态性”(Polymorphism)。

多态性有几种:男厕所类对厕所父类里面的“解小便”有了不同的诠释。这个不同的诠释是由于重写父类的方法而得来的,所以这种多态性叫做基于重写继承(inheritance)的多态,也叫做“override”。

好了,喜欢抬杠的人就发话了:男厕所不是还有尿兜吗?

好了,厕所父类定义了一个解小便的规格,那就是: 解小便(马桶 某马桶,小便者 某人)。 那么在男厕所里面,除了我们有马桶这个属性,另外我们还有“尿兜”这个新属性。 要注意,在“继承”里面,我们强调了继承父类和沿用/复用的特性。但是由于继承产生的子类理所当然也会有自己特有的东西,例如这个男厕所里的尿兜。

男人们因为父类的马桶,而有了自己对使用马桶的诠释,然而还没有对如何使用尿兜的诠释。好在男人们自己发明了一个名称相同,但是参数不同的解小便新规格:解小便(尿兜 某尿兜,小便者 某人), 而其具体实现的方法就是“站着上”。

好了,现在在男厕所里,男人们可以有两个小便的方法可以选择: 解小便(马桶 某马桶,小便者 某人), 实现方法:“坐着上还是站着上,看我心情如何”。 或者: 解小便(尿兜 某尿兜,小便者 某人),实现方法:“站着上”。

这就出现了第二个多态性,叫做同一个类里面基于同名方法的不同签名的多态性,还是老外简单,把这个叫“overload”。要注意override跟overload的区别。

男人可以选择站着或者坐着小便,一会儿override,一会儿overload,不如就叫“多态男”,或者只呼“变态男”算了!

总结一下:所谓面向对象三大特性就是:封装,继承,多态(变态)。

好啦,我们伟大的男厕所建成了!你给了我几百万,我给你盖了个是富丽堂皇、镶金镀银的厕所,不错不错!

不过我忘了告诉你,你还没有对你厕所里的东西定义权限。啥权限啊?就是私有还有共有呗!为啥啊?难道有人跑到厕所里偷马桶盖不成?嘿你真新鲜!连大街上的井葫芦盖都有人偷了去卖钱,偷你个镶金马桶盖还不是小菜?

那咋办?把你的男厕所里面的东西定义成私有啊,这样别人就偷不走了!好,就这么办!让我们来看看男厕所里面都有啥: 两样东西:马桶、尿兜;两个方法:解小便(马桶 某马桶,小便者 某人)、解小便(尿兜 某尿兜,小便者 某人)

我们给这些个东西都上锁,都弄成“私有”,这就保险了!原来面向对象还能保护私有财产,真是个好东西啊!好了,马桶有了,尿兜有了,使用马桶和尿兜的小便方法也有了,锁也上好了,齐了!搞了这么多事儿,您尿憋急了吧?那就赶紧上厕所啊!咋了?还不进厕所?

现在才发现个重要问题:厕所没门儿!

好嘛!建了个富丽堂皇的私有化安全厕所,小偷是进不去了,您自个儿也进不去了!

啥叫高科技垃圾?这就叫高科技垃圾!最后你逼急了,随便在您几百万的厕所外面找个墙角旮旯解决拉倒,不受这洋罪!

好了,等你花了几百万盖了个无门高级厕所,然后你在厕所的墙脚用原始方法解决了以后,我再告诉你:你再给我一百万,让我做第二期工程吧,我来给你装个门, 厕所就能用了。那你肯定会骂:干吗不早说?你傻啊?你不知道挨踢界里面,所有的第一期工程都是没法用的垃圾,然后程序员再向业务部门要钱搞第二期、第三 期……把这个高科技垃圾维持下去,不这么干我们喝西北风去啊?

好了,除了“私有”(Private)这个权限,还有“公有”(public)和“保护”(protected/friendly)等权限(具体到不同的 语言有些些微差别)。其实这三个权限属于前面“封装”的范畴。现在讲讲它们的区别。私有(private)就是完全属于“物主”。产生了一个对象,对象本 身就是“物主”。那么private就是只能物主关在自己的房间里自己用。所以你其实可以使用没有门的高级厕所,前提是要把你也永远关在厕所里面。 “公有”就是顾名思义了。如果是要建公共厕所,这个权限是不能少的。那么“保护”呢?保护的权限相当于家庭厕所。三类人可以用这个厕所:物主(也就是被关在厕所的那位)、物主的子女们(继承了该类的子类们)、同屋的人(在同一个包里的类)。

那么我们该如何应用这些权限呢?有一个趋势,就是所谓的“高内聚,低耦合”(highly cohesive, loosely coupled)。叶雨一下子变得这么学究,你是不是该晕了?好了啦,所谓高内聚就是自己的东西要保管好,低耦合就是“能不上套就不上套”。那么具体到 “男厕所”这个类,什么东西需要高内聚的?马桶,尿兜。我们要确保这两个东西保管好,所以对马桶、尿兜实行“私有”。刚才说过,除非把你关在厕所里不出 来,否则你不能使用私有的马桶跟尿兜。好了,技巧来了:你是不能直接使用私有的马桶跟尿兜,但是你别忘了还有两个定义好的方法啊:两个方法:解小便(马桶 某马桶,小便者 某人)、解小便(尿兜 某尿兜,小便者 某人)。 好了,因为小便方法是男厕所类里面的成员,所以理所当然这两个方法能够直接访问到私有的马桶跟尿兜。然后我们把这两个方法弄成共有的(public)不就 行了吗?这个方法真是天才!一方面我们保证了马桶跟尿兜谁也偷不走,一方面我们可以开放公共厕所了,让大家一起来小便。问题解决啦!

好了,造价高昂的公共厕所正式营业了。你坐在厕所门口收钱,开始觉得回报的时候到了。但是好景不长,里面开始有人嚷嚷他们不能使用马桶!咦?我们不是已经定义了一个解小便的方法了来让大家使用马桶了吗?

一问之下,原来有人想对着马桶解大便,而你只提供了解小便的方法,而没有大便的方法!那你要问了,如果别人知道如何对厕所里的马桶解大便,为啥还要我们提 供解大便的方法啊?这是因为我们已经把马桶“私有”了,所以除了厕所内部定义的方法,否则外部一切的动作都不能直接作用在我们的马桶上。也就是说,你想大 便可以,但是要按我们的方法来!

你看,辛辛苦苦盖了这么好的厕所,只能小便不能大便!顾客们吵着要退钱,你没办法,找挨踢去了,说能不能加个“大便”的方法。那当然欢迎之至了!第三期大便工程,再加一百万!

好了,基本调侃了几个面向对象的概念。还有许许多多具体的细节没有提及。本文毫无章法,纯粹瞎聊,充其量只能引发部分筒子们的学习兴趣。如果真的要有系统地学习这部分知识,还请回去找老学究们的书好了。对本文有任何补充指正,欢迎之至,免费!嗬嗬。

========

分享博文至:

    3 条评论

  1. 1. [email protected] - 2009年10月8日 19:29

    风趣!

  2. 2. zhangblue - 2009年10月9日 15:47

    能否再展开解释一下“highly cohesive, loosely coupled”?

  3. 3. 叶雨 - 2009年10月14日 08:57

    highly cohesive的解释:高内聚,说白了就是模块自成一体。举个例子,厕所一般包含马桶和水龙头。如果不采用高内聚概念去设计厕所的话,那么有可能设计成这个样子:厕所里是有马桶,然后您需要洗手的话,对不起,水龙头在出厕所右拐第三个红绿灯转左。高内聚是提供了方便,但也存在成本问题。

    loosely coupled的解释:低耦合,说白了就是不要被别人套牢。举个例子,厕所里还是马桶跟水龙头。这次我们注意了高内聚的概念,把马桶跟水龙头坐在同一个厕所里了。以为这下方便了。但是如果不采用低耦合的话,比方我们跟A自来水公司签了N年死合同锁定一元/立方,违约金10万元。不久A自来水公司大幅降价,一毛/立方。好了,这就是您没有做到低耦合的后果。

    这里只说概念问题,不涉及编程实例。以后有兴趣可以展开讨论。

发表评论