第1章 对象入门
“为什么面向对象的编程会在软件开发领域造成如此震憾的影响?”
面向对象编程(OOP)具有多方面的吸引力。对管理人员,它实现了更快和更廉价的开发与维护过程。对分析与设计人员,建模处理变得更加简单,能生成清晰、易于维护的设计方案。对程序员,对象模型显得如此高雅和浅显。此外,面向对象工具以及库的巨大威力使编程成为一项更使人愉悦的任务。每个人都可从中获益,至少表面如此。

1.1 抽象的进步
所有编程语言的最终目的都是提供一种“抽象”方法。一种较有争议的说法是:解决问题的复杂程度直接取决于抽象的种类及质量。这儿的“种类”是指准备对什么进行“抽象”?汇编语言是对基础机器的少量抽象。后来的许多“命令式”语言(如FORTRAN,BASIC和C)是对汇编语言的一种抽象。与汇编语言相比,这些语言已有了长足的进步,但它们的抽象原理依然要求我们着重考虑计算机的结构,而非考虑问题本身的结构。
Alan Kay总结了Smalltalk的五大基本特征。这是第一种成功的面向对象程序设计语言,也是Java的基础语言。通过这些特征,我们可理解“纯粹”的面向对象程序设计方法是什么样的:
(1) 所有东西都是对象。可将对象想象成一种新型变量;它保存着数据,但可要求它对自身进行操作。
(2) 程序是一大堆对象的组合;通过消息传递,各对象知道自己该做些什么。为了向对象发出请求,需向那个对象“发送一条消息”。更具体地讲,可将消息想象为一个调用请求,它调用的是从属于目标对象的一个子例程或函数。
(3) 每个对象都有自己的存储空间,可容纳其他对象。或者说,通过封装现有对象,可制作出新型对象。
(4) 每个对象都有一种类型。根据语法,每个对象都是某个“类”的一个“实例”。其中,“类”(Class)是“类型”(Type)的同义词。一个类最重要的特征就是“能将什么消息发给它?”。
(5) 同一类所有对象都能接收相同的消息。这实际是别有含义的一种说法,大家不久便能理解。由于类型为“圆”(Circle)的一个对象也属于类型为“形状”(Shape)的一个对象,所以一个圆完全能接收形状消息。这意味着可让程序代码统一指挥“形状”,令其自动控制所有符合“形状”描述的对象,其中自然包括“圆”。这一特性称为对象的“可替换性”,是OOP最重要的概念之一。

1.2 对象的接口
亚里士多德或许是认真研究“类型”概念的第一人,他曾谈及“鱼类和鸟类”的问题。有些人进行了进一步的区分,他们强调“类型”决定了接口,而“类”是那个接口的一种特殊实现方式。我们向对象发出的请求是通过它的“接口”(Interface)定义的,对象的“类型”或“类”则规定了它的接口形式。“类型”与“接口”的等价或对应关系是面向对象程序设计的基础。

1.3 实现方案的隐藏
略。
1.4 方案的重复使用
创建并测试好一个类后,它应(从理想的角度)代表一个有用的代码单位。但并不象许多人希望的那样,这种重复使用的能力并不容易实现;它要求较多的经验以及洞察力,这样才能设计出一个好的方案,才有可能重复使用。许多人认为代码或设计方案的重复使用是面向对象的程序设计提供的最伟大的一种杠杆。对象的组织具有极大的灵活性。新类的“成员对象”通常设为“私有”(Private),使用这个类的客户程序员不能访问它们。这样一来,我们可在不干扰客户代码的前提下,从容地修改那些成员。也可以在“运行期”更改成员,这进一步增大了灵活性。后面要讲到的“继承”并不具备这种灵活性,因为编译器必须对通过继承创建的类加以限制。

1.5 继承:重新使用接口
就其本身来说,对象的概念可为我们带来极大的便利。它在概念上允许我们将各式各样数据和功能封装到一起。这样便可恰当表达“问题空间”的概念,不用刻意遵照基础机器的表达方式。在程序设计语言中,这些概念则反映为具体的数据类型(使用class关键字)。
在继承过程中,若原始类(正式名称叫作基础类、超类或父类)发生了变化,修改过的“克隆”类(正式名称叫作继承类或者子类)也会反映出这种变化。在Java语言中,继承是通过extends关键字实现的。使用继承时,相当于创建了一个新类。这个新类不仅包含了现有类型的所有成员(尽管private成员被隐藏起来,且不能访问),但更重要的是,它复制了基础类的接口。也就是说,可向基础类的对象发送的所有消息亦可原样发给衍生类的对象。这意味着衍生类具有与基础类相同的类型!有两种做法可将新得的衍生类与原来的基础类区分开。第一种做法十分简单:为衍生类添加新函数(功能)。这些新函数并非基础类接口的一部分。进行这种处理时,一般都是意识到基础类不能满足我们的要求,所以需要添加更多的函数。这是一种最简单、最基本的继承用法,大多数时候都可完美地解决我们的问题。

1.5.1 改善基础类(override覆盖)
尽管extends关键字暗示着我们要为接口“扩展”新功能,但实情并非肯定如此。为区分我们的新类,第二个办法是改变基础类一个现有函数的行为。我们将其称作“改善”那个函数。
为改善一个函数,只需为衍生类的函数建立一个新定义即可。我们的目标是:“尽管使用的函数接口未变,但它的新版本具有不同的表现”。

1.6 多形对象的互换使用
通常,继承最终会以创建一系列类收场,所有类都建立在统一的接口基础上。
对这样的一系列类,我们要进行的一项重要处理就是将衍生类的对象当作基础类的一个对象对待。这一点是非常重要的,因为它意味着我们只需编写单一的代码,令其忽略类型的特定细节,只与基础类打交道。这样一来,那些代码就可与类型信息分开。所以更易编写,也更易理解。此外,若通过继承增添了一种新类型,如“三角形”,那么我们为“几何形状”新类型编写的代码会象在旧类型里一样良好地工作。所以说程序具备了“扩展能力”,具有“扩展性”。
此时,一个Circle(圆)句柄传递给一个本来期待Shape(形状)句柄的函数。由于圆是一种几何形状,所以doStuff()能正确地进行处理。也就是说,凡是doStuff()能发给一个Shape的消息,Circle也能接收。所以这样做是安全的,不会造成错误。
我们将这种把衍生类型当作它的基本类型处理的过程叫作“Upcasting”(上溯造型)。其中,“cast”(造型)是指根据一个现成的模型创建;而“Up”(向上)表明继承的方向是从“上面”来的——即基础类位于顶部,而衍生类在下方展开。所以,根据基础类进行造型就是一个从上面继承的过程,即“Upcasting”。
在面向对象的程序里,通常都要用到上溯造型技术。这是避免去调查准确类型的一个好办法。

1.7.1 集合与继承器(迭代器)
这种新对象通常叫作“集合”(亦叫作一个“容器”)。在需要的时候,集合会自动扩充自己,以便适应我们在其中置入的任何东西。所以我们事先不必知道要在一个集合里容下多少东西。只需创建一个集合,以后的工作让它自己负责好了。
所有集合都提供了相应的读写功能。将某样东西置入集合时,采用的方式是十分明显的。有一个叫作“推”(Push)、“添加”(Add)或其他类似名字的函数用于做这件事情。但将数据从集合中取出的时候,方式却并不总是那么明显。办法就是使用一个“继续器”(Iterator),它属于一种对象,负责选择集合内的元素,并把它们提供给继承器的用户。

1.7.2 单根结构
在面向对象的程序设计中,由于C++的引入而显得尤为突出的一个问题是:所有类最终是否都应从单独一个基础类继承。在Java中(与其他几乎所有OOP语言一样),对这个问题的答案都是肯定的,而且这个终级基础类的名字很简单,就是一个“Object”。这种“单根结构”具有许多方面的优点。单根结构中的所有对象都有一个通用接口,所以它们最终都属于相同的类型。

  1. 下溯造型
    为了使这些集合能够重复使用,或者“再生”,Java提供了一种通用类型,以前曾把它叫作“Object”。单根结构意味着、所有东西归根结底都是一个对象”!所以容纳了Object的一个集合实际可以容纳任何东西。这使我们对它的重复使用变得非常简便。
    为使用这样的一个集合,只需添加指向它的对象句柄即可,以后可以通过句柄重新使用对象。但由于集合只能容纳Object,所以在我们向集合里添加对象句柄时,它会上溯造型成Object,这样便丢失了它的身份或者标识信息。再次使用它的时候,会得到一个Object句柄,而非指向我们早先置入的那个类型的句柄。所以怎样才能归还它的本来面貌,调用早先置入集合的那个对象的有用接口呢?
    在这里,我们再次用到了造型(Cast)。但这一次不是在分级结构中上溯造型成一种更“通用”的类型。而是下溯造型成一种更“特殊”的类型。这种造型方法叫作“下溯造型”(Downcasting)。举个例子来说,我们知道在上溯造型的时候,Circle(圆)属于Shape(几何形状)的一种类型,所以上溯造型是安全的。但我们不知道一个Object到底是Circle还是Shape,所以很难保证下溯造型的安全进行,除非确切地知道自己要操作的是什么。
    但这也不是绝对危险的,因为假如下溯造型成错误的东西,会得到我们称为“违例”(Exception)的一种运行期错误。我们稍后即会对此进行解释。但在从一个集合提取对象句柄时,必须用某种方式准确地记住它们是什么,以保证下溯造型的正确进行。下溯造型和运行期检查都要求花额外的时间来运行程序,而且程序员必须付出额外的精力。既然如此,我们能不能创建一个“智能”集合,令其知道自己容纳的类型呢?这样做可消除下溯造型的必要以及潜在的错误。答案是肯定的,我们可以采用“参数化类型”,它们是编译器能自动定制的类,可与特定的类型配合。例如,通过使用一个参数化集合,编译器可对那个集合进行定制,使其只接受Shape,而且只提取Shape。

1.9 多线程
在计算机编程中,一个基本的概念就是同时对多个任务加以控制。在一个程序中,这些独立运行的片断叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”。多线程处理一个常见的例子就是用户界面。利用线程,用户可按下一个按钮,然后程序会立即作出响应,而不是让用户等待程序完成了当前任务以后才开始响应。解决这个问题,对那些可共享的资源来说(比如打印机),它们在使用期间必须进入锁定状态。所以一个线程可将资源锁定,在完成了它的任务后,再解开(释放)这个锁,使其他线程可以接着使用同样的资源。
Java的多线程机制已内建到语言中,这使一个可能较复杂的问题变得简单起来。对多线程处理的支持是在对象这一级支持的,所以一个执行线程可表达为一个对象。Java也提供了有限的资源锁定方案。它能锁定任何对象占用的内存(内存实际是多种共享资源的一种),所以同一时间只能有一个线程使用特定的内存空间。为达到这个目的,需要使用synchronized关键字。其他类型的资源必须由程序员明确锁定,这通常要求程序员创建一个对象,用它代表一把锁,所有线程在访问那个资源时都必须检查这把锁。

1. 客户机/服务器计算
客户机/服务器系统的基本思想是我们能在一个统一的地方集中存放信息资源。一般将数据集中保存在某个数据库中,根据其他人或者机器的请求将信息投递给对方。客户机/服务器概述的一个关键在于信息是“集中存放”的。所以我们能方便地更改信息,然后将修改过的信息发放给信息的消费者。将各种元素集中到一起,信息仓库、用于投递信息的软件以及信息及软件所在的那台机器,它们联合起来便叫作“服务器”(Server)。而对那些驻留在远程机器上的软件,它们需要与服务器通信,取回信息,进行适当的处理,然后在远程机器上显示出来,这些就叫作“客户”(Client)。
这样看来,客户机/服务器的基本概念并不复杂。这里要注意的一个主要问题是单个服务器需要同时向多个客户提供服务。在这一机制中,通常少不了一套数据库管理系统,使设计人员能将数据布局封装到表格中,以获得最优的使用。除此以外,系统经常允许客户将新信息插入一个服务器。这意味着必须确保客户的新数据不会与其他客户的新数据冲突,或者说需要保证那些数据在加入数据库的时候不会丢失(用数据库的术语来说,这叫作“事务处理”)。客户软件发生了改变之后,它们必须在客户机器上构建、调试以及安装。所有这些会使问题变得比我们一般想象的复杂得多。另外,对多种类型的计算机和操作系统的支持也是一个大问题。最后,性能的问题显得尤为重要:可能会有数百个客户同时向服务器发出请求。所以任何微小的延误都是不能忽视的。为尽可能缓解潜伏的问题,程序员需要谨慎地分散任务的处理负担。一般可以考虑让客户机负担部分处理任务,但有时亦可分派给服务器所在地的其他机器,那些机器亦叫作“中间件”(中间件也用于改进对系统的维护)。

  1. Web是一个巨大的服务器
    Web实际就是一套规模巨大的客户机/服务器系统。但它的情况要复杂一些,因为所有服务器和客户都同时存在于单个网络上面。但我们没必要了解更进一步的细节,因为唯一要关心的就是一次建立同一个服务器的连接,并同它打交道(即使可能要在全世界的范围内搜索正确的服务器)。
    最开始的时候,这是一个简单的单向操作过程。我们向一个服务器发出请求,它向我们回传一个文件,由于本机的浏览器软件(亦即“客户”或“客户程序”)负责解释和格式化,并在我们面前的屏幕上正确地显示出来。但人们不久就不满足于只从一个服务器传递网页。他们希望获得完全的客户机/服务器能力,使客户(程序)也能反馈一些信息到服务器。比如希望对服务器上的数据库进行检索,向服务器添加新信息,或者下一份订单等等(这也提供了比以前的系统更高的安全要求)。在Web的发展过程中,我们可以很清晰地看出这些令人心喜的变化。
    Web浏览器的发展终于迈出了重要的一步:某个信息可在任何类型的计算机上显示出来,毋需任何改动。然而,浏览器仍然显得很原始,在用户迅速增多的要求面前显得有些力不从心。它们的交互能力不够强,而且对服务器和因特网都造成了一定程度的干扰。这是由于每次采取一些要求编程的操作时,必须将信息反馈回服务器,在服务器那一端进行处理。所以完全可能需要等待数秒乃至数分钟的时间才会发现自己刚才拼错了一个单词。由于浏览器只是一个纯粹的查看程序,所以连最简单的计算任务都不能进行(当然在另一方面,它也显得非常安全,因为不能在本机上面执行任何程序,避开了程序错误或者病毒的骚扰)。
    为解决这个问题,人们采取了许多不同的方法。最开始的时候,人们对图形标准进行了改进,使浏览器能显示更好的动画和视频。为解决剩下的问题,唯一的办法就是在客户端(浏览器)内运行程序。这就叫作“客户端编程”,它是对传统的“服务器端编程”的一个非常重要的拓展。

1.11.2 客户端编程(注释⑧)
Web最初采用的“服务器-浏览器”方案可提供交互式内容,但这种交互能力完全由服务器提供,为服务器和因特网带来了不小的负担。服务器一般为客户浏览器产生静态网页,由后者简单地解释并显示出来。基本HTML语言提供了简单的数据收集机制:文字输入框、复选框、单选钮、列表以及下拉列表等,另外还有一个按钮,只能由程序规定重新设置表单中的数据,以便回传给服务器。用户提交的信息通过所有Web服务器均能支持的“通用网关接口”(CGI)回传到服务器。包含在提交数据中的文字指示CGI该如何操作。最常见的行动是运行位于服务器的一个程序。那个程序一般保存在一个名为“cgi-bin”的目录中(按下Web页内的一个按钮时,请注意一下浏览器顶部的地址窗,经常都能发现“cgi-bin”的字样)。大多数语言都可用来编制这些程序,但其中最常见的是Perl。这是由于Perl是专为文字的处理及解释而设计的,所以能在任何服务器上安装和使用,无论采用的处理器或操作系统是什么。

⑧:本节内容改编自某位作者的一篇文章。那篇文章最早出现在位于www.mainspring.com的Mainspring上。本节的采用已征得了对方的同意。
今天的许多Web站点都严格地建立在CGI的基础上,事实上几乎所有事情都可用CGI做到。唯一的问题就是响应时间。CGI程序的响应取决于需要传送多少数据,以及服务器和因特网两方面的负担有多重(而且CGI程序的启动比较慢)。Web的早期设计者并未预料到当初绰绰有余的带宽很快就变得不够用,这正是大量应用充斥网上造成的结果。例如,此时任何形式的动态图形显示都几乎不能连贯地显示,因为此时必须创建一个GIF文件,再将图形的每种变化从服务器传递给客户。而且大家应该对输入表单上的数据校验有着深刻的体会。原来的方法是我们按下网页上的提交按钮(Submit);数据回传给服务器;服务器启动一个CGI程序,检查用户输入是否有错;格式化一个HTML页,通知可能遇到的错误,并将这个页回传给我们;随后必须回到原先那个表单页,再输入一遍。这种方法不仅速度非常慢,也显得非常繁琐。
解决的办法就是客户端的程序设计。运行Web浏览器的大多数机器都拥有足够强的能力,可进行其他大量工作。与此同时,原始的静态HTML方法仍然可以采用,它会一直等到服务器送回下一个页。客户端编程意味着Web浏览器可获得更充分的利用,并可有效改善Web服务器的交互(互动)能力。
对客户端编程的讨论与常规编程问题的讨论并没有太大的区别。采用的参数肯定是相同的,只是运行的平台不同:Web浏览器就象一个有限的操作系统。无论如何,我们仍然需要编程,仍然会在客户端编程中遇到大量问题,同时也有很多解决的方案。在本节剩下的部分里,我们将对这些问题进行一番概括,并介绍在客户端编程中采取的对策。

感谢Bruce Eckel 。

Think IN JAVA 第一章对象入门相关推荐

  1. java基础 第一章 对象入门

    第1章 对象入门 "为什么面向对象的编程会在软件开发领域造成如此震憾的影响?" 面向对象编程(OOP)具有多方面的吸引力.对管理人员,它实现了更快和更廉价的开发与维护过程.对分析与 ...

  2. Thinking in java第一章对象导论

    这一章,做笔记感觉不是很好做.每个人又每个人对面向对象的理解.这里说一下书里的关键字,穿插一下自己的思想 面向对象的编程语言里面很流行的一句话,一切都是对象.面向对象的核心就是抽象,抽象的能力有大有小 ...

  3. Java Persistence with MyBatis 3(中文版) 第一章 MyBatis入门

    本章将涵盖以下话题: ž  MyBatis是什么? ž  为什么选择MyBatis? ž  MyBatis安装配置 ž  域模型样例 1.1 MyBatis是什么 MyBatis是一个简化和实现了Ja ...

  4. 【MyBatis】第一章 快速入门

    第一章 快速入门 文章目录 第一章 快速入门 一.介绍 1.使用 JDBC 的缺陷 2.MyBatis 框架解决的主要问题 二.入门案例 1.准备数据库 2.创建实体类 3.创建持久层 DAO 接口 ...

  5. 第1章 对象入门——Thinking-in-Java

    第1章 对象入门 "为什么面向对象的编程会在软件开发领域造成如此震憾的影响?" 面向对象编程(OOP)具有多方面的吸引力.对管理人员,它实现了更快和更廉价的开发与维护过程.对分析与 ...

  6. Spring入门到精通:第一章 基础入门:1.Spring框架概述

    Spring入门到精通:第一章 基础入门:1.Spring框架概述 前言:为什么要学习Spring框架? 为什么要学习Spring框架呐? (1)使用广泛:现在很多的企业都有Spring的影子,不管是 ...

  7. Android项目驱动式开发教程 第2版,《Android项目驱动式开发教程》第一章开发入门.ppt...

    <Android项目驱动式开发教程>第一章开发入门 1.4 项目框架分析 4 android:versionName="1.0" > 5 8 第9行代码andro ...

  8. 第一章---对象导论

    第一章   对象导论 1.1  抽象过程: 1)万物皆为对象 程序是对象的集合,他们通过发送消息来告知彼此要做的事:想要请求一个对象,就必须向该对象发送一条消息,可以把消息想象成对某个特定对象的方法的 ...

  9. 【MyBatis-Plus】第一章 快速入门

    第一章 快速入门 文章目录 第一章 快速入门 一.介绍 1.概述 2.特性 二.入门案例 1.安装插件 2.准备工作 3.MyBatis-Puls 替换 MyBatis 4.修改 StudentDao ...

最新文章

  1. Google Duplex语气自然流利,外媒却质疑其演示通话录音是伪造的
  2. 编程之美 2.4 1的数目
  3. Rest 微服务工程搭建02——微服务消费者订单Module模块 || @RequestBody 的重要作用
  4. SpringCloud -创建统一的依赖管理
  5. 计算机视觉与深度学习 | 目标检测综述(RCNN、RPN、YOLOv1 v2 v3、FPN、Mask RCNN、SSD代码类)
  6. 职场思想分享001 | 有多种选择才叫有能力
  7. spingmvc 通过xml配置redis jedispol 有密码 通过xml配置redis中的 jedispool(有密码)
  8. 具有GlassFish和一致性的高性能JPA –第1部分
  9. NOIP模拟测试6「那一天我们许下约定(背包dp)·那一天她离我而去」
  10. 用js来实现那些数据结构12(散列表)
  11. 程序员如何理解客户需求
  12. js类型判断(数字、0、、undefined、null)
  13. JAVA随机抽取一名幸运观众(手动输入观众)小实例
  14. 如何将多个图片批量转换成pdf文件?
  15. 网络触发的detach
  16. Tekton实战案例--S2I
  17. 模型微调(finetune)
  18. ZigBee自组网地址分配与路由协议技术详解
  19. Android驱动-霍尔摁键hall_sensor的实现
  20. 【SCF CLI实践】腾讯云serverless + 企业微信群机器人,轻松解决告警通知问题

热门文章

  1. 微型计算机cpu每执行,微型计算机及接口技术2017年4月真题试题(04732)
  2. 「轮子工厂」谭庆波,很高兴认识大家!
  3. 18春学期《计算机应用基础》在线作业1,18春学期《计算机应用基础》在线作业1...
  4. 山东春考计算机很难录取吗,山东春季高考很难录取吗?春季高考考试难吗?
  5. BSOJ 1111 战略游戏
  6. 乘法口诀表python_学习python之编写简单乘法口诀表实现代码
  7. 如何实现一个TCC分布式事务框架
  8. ASP.NET母版页
  9. github之移动文件
  10. Jgit基础教程(Java调用git)