第一章 对象导论
面向对象程序设计 Object-oriented Programming, OOP
1.1 抽象过程
- 所有编程语言都提供抽象机制,人们解决问题的复杂性直接取决于抽象的类型和质量
- 汇编语言是对底层机器的轻微抽象,其他“命令式”语言(BASIC、C等)是对汇编语言的抽象,都要求在解决问题时要基于计算机的结构,必须建立起在机器模型和实际待解问题的模型之间的映射。
- 我们将问题空间中的元素及其在解空间中的表示称为:对象。程序可以通过添加新类型的对象来使自身适用于某个特定的问题。OOP允许根据问题来描述问题,而不是根据运行解决方案的计算机来描述问题。
- 对象具有状态、行为和标识
1.2 每个对象都有一个接口
- 创建抽象数据类型(类)是面向对象程序设计的基本概念之一
- 所有的面向对象程序设计语言都使用class这个关键词来表示数据类型
- 类描述了具有相同特性(数据元素)和行为(功能)的对象集合,所以一个类实际上就是一个数据类型
- 一旦类被建立就可以随心所欲地创建类的任意个对象。事实上,面向对象程序设计的挑战之一就是在问题空间的元素和解空间的对象之间创建一对一的映射
- 每个对象都只能满足某些请求,这些请求由对象的接口(interface)所定义,决定接口的便是类型,接口确定了对某一特定对象所能发出的请求。
1.3 每个对象都提供服务
- 每个对象都良好地完成一项任务,但是它并不试图做更多的事
- 将对象作为服务提供者看待
1.4 被隐藏的具体实现
- java用三个关键字在类的内部设边界:public、private、protected,这些访问指定词决定了紧跟其后被定义的东西可以被谁使用
- public: 紧随其后的元素对任何人都可以使用
- private: 除了类型的创建者和类型内部方法之外的任何人都不能访问的元素
- protected:与private作用基本相当,差别仅在于:继承的类可以访问protected成员,但是不能访问private成员
- 默认的访问权限: 在没有使用前面三种访问指定词的时候,它发挥作用。也称为:包访问权限,在这种权限下,类可以访问在同一个包(库构件)中的其他类的成员,但是在包之外,这些成员如同指定了private一样。
1.5 复用具体实现
- 最简单的复用某个类的方式就是直接使用该类的一个对象
- 复用的其他情况:我们也可以将类的一个对象置于某个新的类中,称其为“创建一个成员对象”。
- 新的类可以由任意数量、任意类型的其他对象以任意可以实现新的类中想要的功能的方式所组成。
- 由现有的类合成新的类,所以这种概念称为“组合”(composition)
- 建立新类时首先考虑组合,因为它比继承更加简单灵活
- 新类的成员对象(回看1)通常被声明为private,使得使用新类的客户端程序员不能访问他们。
1.6 继承
- 基类和导出类具有相同的基础接口,所以导出类与基类具有相同的类型、拥有相同的行为。
- 两种方法使得基类和导出类产生差异:
- 直接在导出类中添加新方法,这些新方法并不是基类接口的一部分
- 改变现有基类的方法(称之为“覆盖那个方法”):想覆盖某个方法可以直接在导出类中创建该方法的新定义即可“此时我正在使用相同的接口方法,但是我想在新类型中做些不同的事情”
1.7 伴随多态的可互换对象
- 经常需要用到的不一定是该对象的特定类型,也可能是需要把该对象当做其基类的对象来对待。
- 编译器不产生传统意义上的函数调用
- 传统的非面向对象的编译器:作前期绑定:编译器将产生对一个具体函数名字的调用,而运行时将这个调用解析到将要被执行的代码的绝对地址
- OOP中使用后期绑定:编译器确保被调用方法的存在并对调用参数和返回值类型检查,但是并不知道将被执行的确切代码。
- java用一小段代码来替代绝对地址调用,这段代码使用在对象中存储的信息来计算方法体的地址
- java中动态绑定是默认的,不用像c++一样使用virtual关键字来实现多态
- 将导出类看做是它的基类的过程称为“向上转型”(upcasting)
1.8 单根继承结构
- 所有的类都继承自单一的基类,这个终极基类的名字:Object
- 在单根继承结构中所有对象都有一个共用接口
- 单根继承结构保证所有对象都具有某些功能,在自己的系统中可以再每个对象中执行某些基本操作
- 所有对象都可以很容易地在堆上创建,而参数传递也得到了极大地简化
1.9 容器
- 容器:任何需要的时候都可以扩充自己以容纳我们置于其中的所有东西,不需要知道将来会把多少个对象置于容器中,只需要创建一个容器对象,然后它自己处理所有细节。
- 范型:增加参数化类型之后的容器,一对尖括号中间包含类型信息,可以用下面的语句来创建一个存储Shape的ArrayList:
ArrayList<Shape> shaps = new ArrayList<Shape>();
1.10 对象的创建和生命期
- 每个对象为了生存都需要资源,尤其是内存,当我们不再需要一个对象时,必须清理掉,使其占有的资源得到释放和重用
- c++追求效率控制,对象的存储空间和生命周期可以再编写程序时确定,将对象置于堆栈或静态存储区域
- java采用了完全的动态内存分配方式,在想要创建新对象的时候,使用new关键字来构建此对象的动态实例
- 动态内存分配:在堆(heap)的内存池中动态地创建对象,直到运行时才知道需要多少对象、他们的生命周期如何、具体类型是什么。在程序执行时相关代码被执行的那一刻才能确定。
- 动态:如果需要一个新对象,可以再需要的时刻直接在堆中创建。动态方式需要大量时间在堆中分配存储空间,要远远大于在堆栈中创建存储空间的时间。在堆栈中创建和释放存储空间通常各自需要一条汇编指令即可,(栈顶指针向下移动和栈顶指针向上移动)
- java提供了垃圾回收器的机制,自动发现对象何时不再被用的时候销毁它。
1.11 异常处理:处理错误
- 异常是一种对象,它从出错地点被“抛出”,并被专门设计用来处理特定类型错误的相应的异常处理器“捕获”
- 异常处理就像是和正常程序执行路径并行的,在错误发生时执行的另一条路径
- 异常不能被忽略,一定在某处得到处理
- 异常提供了一种从错误状况进行可靠恢复的路径,可以进行校正来恢复程序的执行
1.12 并发编程
- 把问题切分成多个可独立运行的部分(任务),程序中这些彼此独立运行的部分称为线程。程序在逻辑上划分成线程。java的并发是内置于语言中的
1.13 Java与Internet
Java解决了万维网(WWW)上的程序设计的问题
1. Web是什么
- 客户服务器计算技术
- 客户/服务器系统的核心思想:系统具有一个中央信息存储池(central repository of information),用来存储某些数据,可以根据需要将它分发给某些人员或者机器集群。信息存储池可以被修改并将这些修改传播给信息消费者。
- 信息存储池、用于分发信息的软件、信息与软件驻留的机器或机群被总称为服务器。
- 驻留在用户机器上的软件与服务器进行通信,以获取信息、处理信息,然后将他们显示在被称为“客户机”的用户机器上
- Web就是一台巨型服务器
- Web实际上就是一个巨型客户/服务器系统,所有的服务器和客户机都处于同一个庞大的网络中,需要实现客户机和服务器的交互(互相发送信息的双向过程)
2. 客户端编程
- 最初的Web“服务器—浏览器”的设计是为了提供交互式的内容,但是其交互性完全由服务器提供。服务器产生静态页面并提供给只能解释并显示他们的客户端浏览器。
- 大多数运行Web浏览器的机器都是能够执行大型任务的强有力的引擎。在使用原始的静态HTML方式的情况下,它们只是闲在那里,等着服务器送来下一个页面。客户端编程意味着Web浏览器能用来执行任何它可以完成的工作,使得返回给用户的结果更加迅速,增强交互性
- 客户端编程与传统意义上的编程相比,参数几乎相同,而平台却不同,Web浏览器就像一个功能受限的操作系统
- 插件
- 插件(plug-in)的开发:程序员可以下载一段代码然后将其插入到浏览器的适当位置,以此来为浏览器添加新功能。
- 脚本语言
- 插件引发了浏览器脚本语言(scripting language)的开发,通过使用某种脚本语言,我们可以将客户端程序的源代码直接嵌入到HTML界面中,解释这种语言的插件在HTML页面被显示时自动激活。(JavaScript在web浏览器不需要任何插件的情况下就可以得到支持)
- web浏览器内部使用脚本语言实际上总是被用来创建更丰富更具有交互性的图形化用户界面(graphic user interface GUI)
- 脚本语言提供了更容易更快捷的开发方式,在考虑诸如java这样更复杂的解决方案之前应该先考虑脚本语言
- Java
Java通过applet以及使用Java Web Start来进行客户端编程 - .NET和C#
.NET平台大致相当于Java虚拟机(JVM,即执行Java程序的软件平台)和Java类库,C#类似于Java - Internet和Intranet
当web技术仅限用于特定公司的信息网络时,被称为Intranet(企业内部网),比Internet有更好地安全性
3.服务器端编程
1.14 总结
- 过程型语言:数据定义和函数调用
- OOP:用来表示问题空间概念的对象,以及发送给这些对象的用来表示在此空间内的行为的消息。