从0开始学编程(17)–面向对象思想了解

  categories:0基础编程  author:

面向对象技术是一种以对象为基础,以事件消息来驱动对象执行处理的程序设计技术。 是我们编程中重要概念,我们还是采用燕老师的 php为例子学习一下什么是面向对象技术。

http://pan.baidu.com/s/1gdpKR9T     d2ue

面向对象技术是个很抽象的例子, 很难一下子学会, 上面的文章大家看一遍, 能熟悉多少都是胜利。

另外下面是从网络上获取的面向对象的介绍, 可以参考。

它以数据为中心而不是以功能为中心来描述系统,数据相对于功能而言具有更强的稳定性。它将数据和对面向对象技术是一种以对象为基础,以事件或消息来驱动对象执行处理的程序设计技术。

它将数据和对数据的操作封装在一起,作为一个整体来处理,采用数据抽象和信息隐蔽技术,将这个整体抽象成一种新的数据类型——类,并且考虑不同类之间的联系和类的重用性。类的集成度越高,就越适合大型应用程序的开发。另一方面,面向对象程序的控制流程由运行时各种事件的实际发生来触发,而不再由预定顺序来决定,更符合实际。事件驱动程序的执行围绕消息的产生与处理,靠消息循环机制来实现。在实际编程时可以采用搭积木的方式来组织程序,站在“巨人”的肩上实现自己的目标。面向对象程序的设计方法使得程序结构清晰、简单,提高了代码的重用性,有效减少了程序的维护量,提高了软件的开发效率

    接触面向对象思想的时候,接触到的第一个概念应该就是“类”,我们一直在讨论诸如如何设计类、如何实现类等高深的问题,但是我们有没有思索过到底什么叫做“类”,类的本质是什么?。按照大多数的面向对象的书籍中的介绍来看,类就是一个数据结构,封装了数据和操作,对于这样的答案,我估计大家都不会满意。
那到底什么是类呢?在讨论这个问题之前,我们先探讨一下类的由来。“类”在英语对应的单词是“Class”,如果大家翻一翻英语词典就可以查到“Class”的原意是指“种类、把…分类(或分等级)”。Class的概念最早应该是从分类学来的,意思是把对象进行归类(说的可能有些不太准确,欢迎那位高人指正),例如生物学上会根据某一个标准将生物分为动物和植物两大类,然后再根据其它的一些标准将动物又分为鱼类、爬行动物类、两栖动物类等不同的种类,如下图所示:

说到这里,可能大家会欢呼:原来面向对象的类就是分类,太好了!我最擅长这个了!别高兴的太早,谁知道面向对象的分类标准是什么吗?是生物学的标准,还是能不能爬树的标准?不同的标准,导致分类的结果完全不同,如下图所示:

假设现在需要要写一个弹涂鱼的类(又名虾虎鱼,英文名为Goby,一种可以爬上陆地并且会上树的鱼类,据说味道极其鲜美,有海上人参之说) ,怎么写?是不是太容易了,看下面的代码,分分钟就搞定了:

 1 ‘鱼
2 Public Class Fish
3
4 End Class
5
6 ‘可爬树的鱼
7 Public Class ClimbableFish
8     Inherits Fish
9
10 End Class
11
12 ‘弹涂鱼
13 Public Class Goby
14     Inherits ClimbableFish
15
16 End Class

打完收功,貌似很完美的解决问题,但是这个时候又添加了一个分类标准,能吃的鱼和不能吃的鱼(鲨鱼能吃,俺吃过,味道不咋地,在这里假设鲨鱼不能吃),又该怎么办,Stupid,再写一个“EatableFish” 类不就得了,让可爱的弹涂鱼从可以吃的鱼派生,我最喜欢能吃的鱼了!且慢!动手之前我想搞清楚一个问题:EatableFish从那个类派生?从 ClimbableFish类派生?难道可以吃的鱼都是会爬树的鱼?从Fish派生,那么是不是说会爬树的鱼都不能吃?这个时候是不是该咒骂微软为什么不 在.NET中支持多重继承?算了,还是转投Java阵营算了。旁边的一位兄弟弱弱的来了一句:好像Java也不支持多重继承吧。怎么办?难道我们就没有办 法解决这个问题了吗?
貌似用分类学的搞法搞不定面向对象的类耶,我们错了吗?但是很多教科书上面就是这么说的类的继承是“Is A”(是一个)的关系呀,弹涂鱼是“Is A”能吃的鱼、弹涂鱼“Is A” 能爬树的鱼,念起来蛮通顺的嘛。错了!我们都被教科书给误导了!面向对象关注什么?关注的是对象的行为,面向对象是使用行为来对对象进行分类的!在面向对 象中派生类为什么能够替换基类(替换原则),不是因为派生类是一个基类,而是因为派生类具有与基类一致的行为,在派生类与基类的行为不一致的情况下派生类 仍然是一个基类(如果有人敢否认这个,大家说怎么办?旁边有人喊道:砍死他!),但是这个时候派生类消减了基类的行为,违背了替换原则,这也是恶心设计的 由来。所以说,对于面向对象而言我们要关注“Act As”,用“Act As”的标准来对对象进行归类,至于什么“Is A”之类的伪标准统统扔到它姥姥家去。
旁边有人不干了:你跟我说说属性是什么动作!对呀,属性是个什么动作呢?那么请有如此疑问的朋友仔细的考虑一下,是不是可以将属性考虑为GetXXX和 SetXXX的两个方法,至于说字段怎么怎么地的某些兄弟俺就不多说了,回去自个好好想想吧,有些东西是属于开发平台为我们做了很多的工作,只不过我们不 知道而已。
好,问题到这里已经有些眉目了,我们该讨论如何使用“Act As”来对对象进行分类了。
高手出招了,代码如下:

 //可爱的小鱼接口
public interface IFish
{
}//可爱的爬树接口
public interface IClimbable
{
}//可以吃接口
public interface IEatable
{
}

//弹涂鱼出场了
//我要扮演鱼
//我要扮演爬树高手
//我要扮演可以吃的美味,貌似没有人愿意扮演这个
public class Goby : IFish, IClimbable, IEatable
{
}

高手!请问我需要怎样表演才能扮演成一条鱼呢?高手愕然。
看来我们的高手还是没有摆脱“Is A”的荼毒呀!我们不要鱼!我们要的是行为!行为由什么决定的呢?由要用你这个类的地方期望要的行为来决定的,例如我需要一个能够提供游泳行为的对象,你 就可以抽象”ISwimable”这个动作(这个单词可能不对),然后寻求实现这个动作的对象就可以了(接口倒置原则)。
有些朋友可能会有一些疑问,既然是动作,那么动作之间怎么会有继承呢(接口的继承)?例如:

 //我是一个数据提供源
public interface IDataSource : IDisposable
{
}

仔细想想,这个是继承吗?是“Is A”吗?不是!不知道大家玩过拳皇或者其它的格斗游戏没有,要知道分别连续按键是可以组合出一个大招的,在某些情况下,对象的使用者或者理论一点的说法消 费者,需要是对象同时提供上述的两种行为,不过分吧。软件设计的时候往往就是这个地方出问题,如果没有分清楚的话,很有可能把本应该拆分的动作当作一套组 合拳给打了(接口隔离原则),这也是混乱的开始,重构的原因。
我们一直以来都从“Is A”的角度来对对象进行归类,但是仔细的想一想,“Is A”的标准是什么?我们怎么样才能判定一个对象“Is A”另外一个对象呢?大家是不是基本靠猜测或者凭经验在做?这也是软件设计一直被当作是一种艺术行为的原因。一下这个图是我的一个观点,请大家参考一下:

其中箭头表示对象的行为,我们关注的行为是指落在系统范围之内的行为,或者系统关心的行为。
好了,今天就写到这里吧,以后有时间我会再详细的讨论如何分拆动作,如何设计类的话题。



快乐成长 每天进步一点点