第一章 · 对象导论
1.1 抽象过程
所有语言都提供抽象机制。可以认为,人们所能解决问题的复杂性直接取决于抽象的类型和质量。
OOP允许根据问题描述问题,它这种思想的实质就是:程序可以通过添加新类型的对象使得自身适用于某个特定问题
OOP的特性:
- 万物皆为对象。
- 程序是对象的集合,它们通过发送消息来告知彼此所要做的。
- 每个对象都有自己的由其他对象所构成的存储。
- 每个对象都拥有其类型。
- 某一个特定类型的所有对象都可以接收同样的消息。
1.2 每个对象都有一个接口
一个类实际上就是一个数据类型,因为它描述了具有相同特性(数据元素)和行为(功能)的对象集合。
面向对象程序设计的挑战之一:是在问题空间的元素和解空间的对象之间创建一对一的映射。
1.3 每个对象都提供服务
将对象作为服务提供者看待是一件伟大的简化工具,既可以将抽象问题合理的分解为小的一块块,又可以提高对象的内聚性。
在良好的面向对象设计中,每个对象都可以很高的完成一项任务,而不去试图完成更多的东西。
1.4 被隐藏的具体实现
Java使用三个关键字在类的内部设定边界:public, private, protect。
访问控制的第一个原因:
- 让客户端程序员无法触及他们不应该触及的部分。这些部分对数据类型的内部操作来说是必须的,但不是用户解决特定问题所需要的接口的一部分。
- 允许库类设计者可以改变内部某些具体实现而不用担心会影响到客户端程序员。
1.5 复用具体类型
“创建一个成员对象”是最简单直接的复用类的方式。
新的类可以由任意数量、任意类型的其他对象以任意可以实现新的类型中想要的功能的方式所组成。因为是在使用现有的类合成新的类,所以这种概念被称为“组合”,如果组合是动态发生的,就称为“聚合”。
在建立新类时,应该首先考虑组合(更加简单灵活)。
1.6 继承
基类,导出类
继承使用基类型和导出类型的概念表示了这种类型之间的相似。
继承一个类时,同时创建了一个新的类型,但它不仅复制了上一个类的所有成员,更重要的是复制了上一个类的接口,也就是说,所有可以发送给基类对象的消息同时也可以发送给导出类对象。由于通过发送给对象的消息的类型可知对象的类型,意味着导出类对象和基类对象具有相同的类型。
俩种方法使基类导出类产生差异:
- 直接在导出类中添加新方法
- 覆盖现有基类的方法的行为
1.6.1 “是一个”和“像是一个”的关系
直接在导出类中添加方法,导出类中包含新的接口,基类和导出类是“像是一个”的关系,基类对象无法访问新添加的方法。
导出类对基类中的方法进行覆写,俩者的关系“是一个”,因为它们的接口完全一样(不过具体实现不同)。结果可以用一个导出类对象完全替代一个基类对象。这可以被视为纯粹替代,通常称之为“替代原则”。
1.7 伴随多态的可互换对象
面向对象程序设计语言的编译器不可能产生传统意义上的函数调用,为了解决这个问题,面向对象程序设计语言使用了后期绑定的概念。
void doSomething(Shape shape){shape.erase( );shape.draw()}
Circle circle = new Circle;
Trangle triangle = new Trangle();
Line line = new Line();
doSomething(circle); doSomething(triangle); doSomething(line);
把导出类看作是它的基类的过程称为向上转型
1.8 单根继承结构
在Java中(事实上包括所有的除C++之外的OOP语言),所有的类最终都继承自单一的基类——Object
1.9 容器
为了解决知道在处理某个问题时需要多少个对象,或者它们将存活多久,那么就不可能知道如何存储这些对象。如何才能知道需要多少空间来创建这些对象的问题,创造了容器的概念。
1.9.1 参数化类型
参数化类型是一个编译器可以自动定制作用于特定类型上的类
Java中它又称为泛型。一对尖括号,中间包含类型信息。
1.10 对象的创建和生命期
对象的创建
Java完全采用了动态内存分配方式
动态方式有一个一般性的逻辑假设:对象趋向于变得复杂,所以查找和释放存储空间的开销不会对对象的创建造成重大影响。
对象的生命期
对象在堆上创建的,所以编译器对它的生命周期一无所知。Java为此提供了垃圾回收机制,其被设计用来处理内存释放问题。
这一点同所有对象都是继承自根基类Object以及只能用一种方式创建对象(在堆上创建)俩个特性结合起来,使得Java编程的过程较之用C++编程要简单得多,所要做出的决策和要克服的障碍也要少得多
1.11 异常处理:处理错误
异常是一种对象
异常从出错地点被抛出,并被专门设计用来处理特定类型错误的相应的异常处理器“捕获”。
异常处理器就像与程序正常执行路径并行的、在错误发生时执行的另一条路径。因为它是另一条完全分离的执行路径,所以它不会干扰正常的执行代码。
异常不能被忽略
程序抛出的异常保证一定会在某处得到处理。
异常提供了一种从错误状况进行可靠恢复的途径。有助于编写出更健壮的程序。
1.12 并发编程
**在程序中,问题被切分为多个可以独立运行的部分(任务),这些彼此独立的部分称之为线程;停下正在执行的任务,转而处理其他任务,然后再返回主进程,被称为并发。
隐患:资源共享
1.13 Java和Internet
Java为解决在万维网上的程序设计问题提供了极大的便利
1.13.1 web是什么
1. 客户/服务器计算技术
核心思想
系统具有一个中央信息储存池,用来存储某种数据,他通常存在于数据库中,你可以通过需要将它分发给某些人或者机器集群。
关键
信息储存池的位置集中于中央,这使得它可以被修改,并且这些修改将被传播给信息消费者。
通常,还会涉及到数据库管理系统
最后,最重要的性能问题
可能在任意时刻都有成百上千的客户向服务器发送请求,任何小的延迟都会产生重大的影响。为了将延迟最小化,程序员努力减轻处理任务的负载,通常是分散给客户端机器处理,但有时候也会使用所谓的中间件将负载分散给在服务器端的其他机器(中间件可以提高可维护性)。
2. Web就是一台巨型服务器
Web实际上就是一个巨型客户/服务器系统,但稍微差一点,因为所有的服务器和客户机都同时共存于同一个网络中。
1.13.2 客户端编程
客户端编程意味着Web浏览器能用来执行任何它可以完成的工作,使得返回给用户的结果更加迅捷,而且使得你的网站更加具有交互性。
问题是:与通常意义上的编程十分不同,参数几乎相同,而平台不同。
Web浏览器就像一个功能受限的操作系统。
1.插件
下载一段代买,安装到正确位置,以此为浏览器添加新功能。
价值在于允许专家级的程序员不必经过浏览器生产厂商的许可,就可以开发某种语言扩展(不仅限于Java这种开发语言),并且把它添加到服务器中。
2.脚本语言
插件引发了脚本语言的开发。通过使用某种脚本语言,你可以将客户端程序的源代码直接嵌入到HTML界面中,解释这种语言的插件在HTML页面被显示时自动激活。
3.Java
Java可以优雅地处理在传统编程语言中难以解决的问题,例如并发、数据库访问、网络编程和分布式计算。Java是通过applet以及使用Java Web Start来进行客户端编程的。
4.备选方案
管他妈的,老子现在又接触不到
5.NET和C#
我去你的,用了一次人都裂开了
6.Internet与Intranet
等我毕业进公司再说吧,爱咋咋地
1.13.3 服务器端编程
前面以及提到,服务器端编程涉及到处理数据库事务管理。
1.14 总结
面向对象程序设计给人们的喜悦之一:**对于设计良好的程序,通过阅读它就可以很容易地理解其代码。通常其代码量也会精简,因为很多问题都可以通过重用现有的库类代码而得到解决。