对象导论
1.1 抽象过程(The progress of abstraction)
所有编程语言都提供抽象机制。人们所能够解决的问题的复杂性直接取决于抽象的类型和质量 。
面向对象编程允许根据问题来描述问题,而不是根据运行解决方案的计算机来描述问题。
面向对象编程的五个基本特性,这些特性表现了一种纯粹的面向对象程序设计方式:
1)万物皆为对象。
2)程序是对象的集合,它通过发送消息来告诉彼此所要做的。
3)每个对象都有自己的由其它对象所构成的存储。
4)每个对象都拥有其类型。
5)某一特定类型的所有对象都可以接收同样的消息。
1.2 每个对象都有一个接口(An object has an interface)
总结:这一小节首先介绍了类的思想、面向对象编程语言中类的本质以及怎么才能获得有用的对象(How do you get an object to do useful work for you?)。
类的思想:所有对象都是唯一的,但同时也是具有相同特性和行为的对象所归属的类的一部分。
面向对象编程语言中类的本质:因为类描述了具有相同特性(数据元素)和行为(功能)的对象的集合,所以一个类实际上就是一个数据 类型, 例如浮点型数字是具有相同特性和行为的集合。二者的差异在于,程序员通过定义类来适应问题,而不 再被迫只能使用现有的用来表示机 器中存储单元的数据类型。可以根据需求,通过添加新的数据类型来扩展编程语言。编程 系统欣然接受新的类,并且像对待内置类型一样 来照管它们和进行类型检查。
怎么样才能获得有用的对象:必须有某种方式产生对对象的请求,使对象完成各种任务。这些请求由对象的接口所定义,决定接口的便 是类型。
PS:有些人会对类型(type)和类(class)区别对待,认为类型决定了接口,而类是该接口的一个特定实现。
1.3 每个对象都提供服务(An object provides services)
当正在试图开发或理解一个程序设计时,最好的方法之一就是将对象想象为“服务提供者”。程序本身将向用户提供服务,它将通过调用其它对象提供的服务来实现这一 目的。你的目标就是去创建(或者最好是在现有的代码库中寻找)能够提供理想服务来解决问题的一系列对象。
将对象看作是服务提供者有助于提高对象的内聚性。
在良好的面向对象设计中,每个对象都可以很好地完成一项任务,但是它并不试图做更多的事。
1.4 被隐藏的具体实现
访问控制的第一个存在原因就是让客户端程序员无法触及他们不应该触及的部分——这些部分对数据类型的内部操作来说是必须的部分,但并不是解决特定问题所需的接 口的一部分。
访问控制的第二个存在原因就是允许库设计者可以改变类内部的工作方式而不用担心会影响到客户端程序员。
public表示紧随其后的元素任何人都是可用的;private表示除类型创建者和类内部的方法之外任何人都不能访问;protected与private相当,差别仅在于继承的类可以访问protected成员,但是不能访问private成员;default同一个包中的类可以访问,包外的类不能访问。
1.5 复用具体实现
复用类的方式:一、直接使用该类的一个对象;二、将那个类的一个对象置于新的类中。
使用现有的类组成新的类,这种概念称为组合(composition)。如果组合是动态发生的,它通常称为聚合(aggregation)。
实际上,在建立新类时,应该首先考虑组合,因为它更简单灵活。
1.6 继承
继承解决的问题:当创建一个类后,即使另一个新类与其具有相似的功能,你还是得重新创建一个新类。如果我们能够以现有的类为基础,复制它,然后通过添加和修改这个副本来创建新类那就要好得多了。通过继承便可以达到这样的效果。不过,当源类发生变动时,被修改的副本也会反映出这些变动。
类型不仅描述了作用于一个对象集合上的约束条件,同时还有与其他类型之间的关系。
基类与导出类具有相同的类型。通过继承而产生的类型等价性是理解面向对象程序设计方法内涵的重要门槛。
有两种方法可以使基类与导出类产生差异:一、直接在导出类中添加新的方法;二、改变现有基类的方法,这被称之为覆盖(overriding)。
is-a关系和is-like-a关系
1.7 伴随多态的可互换对象
Why:在处理类型结构时,经常想把一个对象不当做它所属的特定类型来对待,而是将其当做基类的对象来对待。这使得人们可以编写出不依赖于特定类型的代码。这样的代码是不会受添加新类型影响的。