A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© static小白 中级黑马   /  2016-5-31 23:12  /  404 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

一、抽象过程

Smalltalk 的五个基本特性,这些特性表现了一种纯粹的面向对象程序设计方式:

1.  万物皆为对象。将对象视为奇特的变量,它可以存储数据,除此之外,你还可以要求它
在自身上执行操作。理论上讲,你可以抽取待解问题的任何概念化构件(狗、建筑物、
服务等),将其表示为程序中的对象。

2.  程序是对象的集合,它们彼此通过发送消息来调用对方。要想产生一个对对象的请求,
就必须对该对象发送一条消息。更具体地说,你可以把消息想象为对某个特定对象的方
法的调用请求。

3.  每个对象都拥有由其它对象所构成的存储。你可以通过创建包含现有对象集合的包的
方式来创建新类型的对象。因此,你可以在程序中构建复杂的体系,同时将其复杂性通
过对象的质朴性得以屏蔽。

4.  每个对象都拥有其类型(Type)。按照通用的说法,“每个对象都是某个类(Class)的
一个实例(Instance)”,其中“类”就是“类型”的同义词。每个类中最重要的区别于其它
类的特性就是“你可以发送什么消息给它?”

5.  某一特定类型的所有对象都可以接收(Receive)同样的消息。这是一句意味深长的表述,
你在稍后便会看到。因为“圆形(circle)”类型的对象同时也是“几何形(shape)”类型
的对象,所以一个“圆形”对象必定能够接受(accept)发送给“几何形”对象的消息。这
意味着你可以编写与“几何形”交互并自动处理所有与几何形性质相关的事物的的代码。
这种“可替代性(substitutability)”是 OOP中最强有力的概念之一。

二、具体说来,就是每一个对象在内存中都有一个唯一的地址

三、每个对象都提供服务

当你正是如开发或理解一个程序设计时,最好的方法之一就是将对象想象为“服务提供者
(Service Provider)”。你的程序本身将向用户提供服务,它将通过调用其它对象提供的服务
来实现这一目的。你的目标就是去创建(或者最好是在现有代码库中寻找)能够提供理想的
服务来解决问题的对象集合。

将对象看作是服务提供者还有一个附加的好处:它有助于提高对象的内聚性(cohesiveness)。
高内聚是软件设计的基本质量要求之一:这意味着一个软件构件(例如一个对象,尽管它也
有可能被用来指代一个方法或一个对象库)的各个方面“组合(fit together)”得很好。

于是问题产生了,在设计对象时所面临的一个问题是将过多的功能都填塞在一个对象中。
这就需要我们运用良好的编程风格和基础的Java 知识。

1、权限控制

Java 使用三个关键字来在类的内部设定边界:public、private、protected。它们的含义和用
非常易懂。这些“访问指定词(access specifier)”决定了紧跟其后被定义的东西可以被谁
用。public 表示紧随其后的元素对任何人都是可用的,另一方面,private 这个关键字表示
类型创建者和该类型的内部方法之外的任何人都不能访问的元素。private 就像你与客户端
序员之间的一堵砖墙,如果有人试图访问 private 成员,就会在编译时刻得到错误信息
protected 关键字与 private 作用相当,差别仅在于继承类(Inheriting class)可以访问 protecte
成员,但是不能访问 private 成员。稍后将会对继承(Inheritance)进行介绍。

Java 还有一种缺省(default)的访问权限,当你没有使用前面提到的任何访问指定词时,
将发挥作用。这种权限通常被称为“包访问权限(package access)”,因为在这种权限下
类可以访问在同一个包中的其它类的成员,但是在包之外,这些成员如同 private一样。

2、复用具体实现

一旦类被开发并被测试完成,那么它就应该(理想情况下)代表一个有用的代码单元。事实
证明,这种复用性(reusability)并不容易达到我们所希望的那种程度,产生一个可复用的对象
设计需要丰富的经验和敏锐的洞察力。但是一旦你拥有了这样的一个设计,它就会请求被复
用。代码复用是面向对象程序设计语言所提供的最了不起的优点之一。

简单的复用某个类的方式就是直接使用该类的一个对象,此外你也可以将该类的一个对象
于某个新的类中。我们称其为“创建一个成员对象”。新的类可以由任意数量、任意类型
其它对象以任意可以实现新的类中想要的功能的方式所组成。因为你在使用现有的类合成
的类,所以这种概念被称为组合(composition),如果组合式动态发生的,那么它通常被
为聚合(aggregation)。组合经常被视为“has-a”(拥有)关系,就像我们常说的“小汽车拥
引擎”一样。

由于继承在面向对象程序设计中如此重要,所以它经常被高度强调,于是程序员新手就会有
这样的印象:处处都应该使用继承。这会导致难以使用并过分复杂的设计。实际上,在建立
新类时,你应该首先考虑组合,因为它更加简单而灵活。如果你采用这种方式,你的设计会
变得更加清晰。一旦有了一些经验之后,你便能够看透必须使用继承的场合。

3、继承:复用接口

对象这种观念,本身就是十分方便的工具,使得你可以通过概念(concept)将数据和功能
封装到一起,因此你可以对问题域的观念给出恰当的表示,而不用受制于必须使用底层机器
语言。这些概念用关键字 class 来表示,形成了编程语言中的基本单位。

遗憾的是,这样做还是有很多麻烦,在创建了一个类之后,即使另一个新类与其具有相似的
功能,你还是得重新创建一个新类。如果我们能够以现有的类为基础,复制它,然后通过添
加和修改这个副本来创建新类那就要好得多了。通过继承便可以达到这样的效果,不过也有
例外,当源类(被称为基类( base class)、超类(super class)或父类(parent class))发生变动时,
被修改的“副本”(被称为导出类(derived class)、继承类(inherited class)或子类(subclass, child
class))也会反映出这些变动。

当你继承现有类型时,也就创造了新的类型。这个新的类型不仅包括现有类型的所有成员(尽
管 private 成员被隐藏了起来,并且不可访问),而且更重要的是它复制了基类的接口。也就
是说,所有可以发送给基类对象的消息同时也可以发送出导出类。由于我们通过可发送消息
的类型可知类的类型,所以这也就意味着导出类与基类具有相同的类型。在前面的例子中,
“一个圆形也就是一个几何形状”。通过继承而产生的类型等价(type equivalence)是理解
面向对象程序设计方法内涵的重要门槛。

虽然继承有时可能意味着在接口中添加新方法(尤其是在以 extends 关键字表示继承的 Java
中),但并非总需如此。第二种以及其它使导出类和基类之间产生差异的方法是改变现有基
类的方法的行为。这被称之为重载(overriding)。

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马