天天看点

第1章 对象导论

1.1 抽象过程

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

1)万物皆为对象。

2)程序是对象的集合,它们通过发送消息来告知彼此所要做的。

3)每个对象都有自己的由其他对象所构成的存储。

4)每个对象都拥有其类型。

5)某一特定类型的所有对象都可以接收同样的消息。

对象具有状态、行为和标识。这意味着每一个对象都可以拥有内部数据和方法,并且每一个对象都可以唯一地与其他对象区分开来,具体来说,就是每一个对象在内存中都有一个唯一的地址。

1.2 每个对象都有一个接口

类描述了具有相同特征(数据元素)和行为(功能)的对象集合,所以一个类实际上就是一个数据类型。

每个对象都只能满足某些请求,这些请求由对象的接口(interface)所定义,决定接口的便是类型。

1.3 每个对象都提供服务

高内聚是软件设计的基本质量要求之一:这意味着一个软件构件的各个方面“组合”得很好。

在良好的面向对象设计中,每个对象都可以很好地完成一项任务,但是它并不试图做更多的事。

1.4 被隐藏的具体实现

访问控制的第一个存在原因就是让客户端程序员无法触及他们不应该触及的部分。

访问控制的第二个存在原因就是允许库设计者可以改变类内部的工作方式而不用担心会影响到客户端程序员。

JAVA用三个关键字在类的内部设定边界:public、private、protected。这些访问指定词决定了紧跟其后被定义的东西可以被谁使用。public表示紧随其后的元素对任何人都是可用的,而private这个关键字表示除类型创建者和类型的内部方法之外的任何人都不能访问的元素。private就像你与客户端程序员之间的一股砖墙,如果有人试图访问private成员,就会在编译时得到错误信息。protected关键字与private作用相当,差别仅在于继承的类可以访问protected成员,但是不能访问private成员。

Java还有一种默认的访问权限,当没有使用前面提到的任何访问指定词时,它将发挥作用。这种权限通常称为包访问权限,因为在这种权限下,类可以访问在同一个包(库构件)中的其他类的成员,但是在包之外,这些成员如同指定了private一样。

1.5 复用具体实现

代码复用是面向对象程序设计语言所提供的最了不起的优点之一。

因为是在使用现有的类合成新的类,所以这种概念被称为组合(composition),如果组合是动态发生的,那么它通常被称为聚合(aggregation)。

1.6 继承

通过使用对象,类型层次结构成为了主要模型,因此可以直接从真实世界中对系统的描述过渡到代码对系统进行描述。

类与基类具有相同的类型。

有两种方法可以使基类与导出类产生差异。第一种方法非常直接:直接在导出类中添加新方法;第二种也是更重要的一种使导出类与基类之间产生差异的方法是改变现有基类的方法的行为,这被称之为覆盖(overriding)那个方法。

1.7 伴随多态的可互换对象

OOP中,程序直到运行时才能确定代码的地址,所以当消息发送到一个泛化对象时,必须采用其他的机制。

为了解决这个问题,面向对象编程语言使用了后期绑定的概念。当向对象发送消息时,被调用的代码知道运行时才能确定。编译器确保被调用方法的存在,并对调用参数和返回值执行类型检查(无法提供此类保证的语言被称为是弱类型的,比如Python),但是并不知道将被执行的确切代码。

在某些语言中,必须明确地声明某个方法具备后期绑定特性所带来的灵活性(C++使用virtual关键字来实现的)。在这些语言中,方法在默认情况下不是动态绑定的。 而在Java中,动态绑定是默认行为,不需要添加额外的关键字来实现多态。

1.8 单根继承结构

这个终极基类的名字就是Object。

在单根继承中的所有对象都具有一个共用接口,所以他们归根结底都是相同的基本类型。

单根继承结构保证所有对象都具备某些功能。

单根继承结构使垃圾回收器的实现变得容易很多,而垃圾回收器正式java相对于C++的重要改进之一。

1.9 容器

第一,不用容器提供了不同类型的接口与外部行为。

第二,不同的容器对于某些操作具有不同的效率。

1.9.1 参数化类型

向上转型是安全的,除非确切知道所要处理的对象的类型,否则向下转型几乎是不安全的。

参数化类型就是一个编译器可以自动定制作用域特定类型上的类。(泛型)

1.10 对象的创建和生命期

为了追求最大的执行速度,对象的存储空间和声明周期可以在编写程序时确定,这可以通过将对象置于堆栈(它们有时被称为自动变量或限域变量)或静态存储区内来实现。这种方式将存储空间分配和释放置于优先考虑的位置,某些情况下这样控制非常有价值,但是可牺牲了灵活性。

第二种方式是在被称为堆(heap)的内存池中动态地创建对象。在这种方式中,直到运行时才知道需要多少对象,它们的生命周期如何,以及它们的具体类型是什么。

动态方式带来更大的灵活性。

Java完全采用了动态内存分配方式,每当想要创建新对象时,就要使用new关键字来构建此对象的动态实例。

Java提供了成为“垃圾回收器”的机制,它可以自动发现对象何时不再被使用,并继而销毁它。垃圾回收器非常有用,因为它减少了所必须考虑的议题和必须编写的代码。更重要的是,垃圾回收器提供了更高级的保障,可以避免暗藏的内存泄漏问题。

Java的垃圾回收器被设计用来处理内存释放问题(尽管它不包括清理对象的其他方面)。垃圾回收器“知道”对象何时不再被使用,并自动释放对象占用的内存。

1.11 异常处理:处理错误

Java的异常处理在众多的编程语言中格外引人注目,因为Java一开始就内置了异常处理,而且强制你必须使用它,它是唯一可接受的错误报告方式。如果没有编写正确的处理异常的代码,那么就会得到一条编译时的出错信息。这种有保障的一致性有时会使得错误处理非常容易。

1.12 并发编程

线程只是一种为单一处理器分配执行时间的手段。但是如果操作系统支持多处理器,那么每个任务都可以被指派给不同的处理器,并且它们是在真正地并行执行。

1.13 Java与Internet

1.13.1 Web是什么

1. 客户/服务器计算技术

信息存储池、用于分发信息的软件以及信息与软件所驻留的机器或机群被总称为服务器。驻留在用于机器上的软件与服务器进行通信,以获取信息、处理信息,然后将它们显示在被称为客户机的用户机器上。

为了将延迟最小化,程序员努力减轻处理任务的负载,所以任何小的延迟都会产生重大影响,但同时也会使用所谓的中间件将负载分散给服务器端的其他机器。(中间件也被用来提高可维护性。)

2. Web就是一台巨型服务器

web实际上就是一个巨型客户/服务器系统,但稍微差一点,因为所有的服务器和客户机都同时共存于同一个网络中。

1.13.2 客户端编程

这种提交动作通过所有的web服务器都提供的通用网关接口(common gateway interface,CGI)传递。

如果你期望有一种脚本语言在web浏览器不需要任何插件的情况下就可以得到支持,那它非JavaScript莫属。

目前,.NET主要受攻击的地方和人们所关心的最重要的问题就是,微软是否会允许将它完全移植到其他平台上。微软宣称这样做没有问题,而且Mono项目已经有了一个在Linux上运行的.Net的部分实现;但是,在该实现完成以及微软不会排斥其中的任何部分之前,.Net作为一种跨平台的解决方案仍旧是一场高风险的赌博。