Java编程思想——对象导论

来源:互联网 发布:如何把分开的数据整合 编辑:程序博客网 时间:2024/06/05 11:07

1对象导论

1.1抽象过程

所有编程语言都提供抽象机制。可以认为,人们所能够解决的问题的复杂性直接取决于抽象的类型和质量。所谓类型是指“所抽象得是什么”。面向对象方式将问题空间中的元素及其在空间中的表称为“对象”。面向对象的语言大概有一下五个特性:
1)万物皆为对象。可以抽取待求解问题的任何概念化构件(狗,建筑等),将其表示为程序中的对象。
2)程序是对象的集合,他们通过发送消息来告知彼此所要做的事。想要请求一个对象,必须给该对象发送一条消息。,即特定对象的方法调用请求。
3)每个对象都有自己的由其他对象所构成的存储。可以通过创建包含现有对象的包的方式来创建新类型对象。
4)每个对象都有其类型。每个对象都是某个类的实例
5)某一特定类型的所有对象都可以接受同样的消息。

1.2每一个对象都有一个接口

在程序执行期间具有不同的状态而其他方面都相似的对象会被分到对象的类中,即关键字class由来。创建抽象数据类型(类)是面向对象程序设计个基本概念之一。抽象数据类型的运行方式与内置类型几乎一致:创建某一类型的变量(对象或实例),然后操作这些变量。其中每一个对象都属于定义了特性和行为的某个特定类。
一个电灯泡接口实例
每个对象都只能满足某些请求,这些请求由对象的接口定义,决定接口的便是类型。如上图的电灯泡。

1.3每个对象都提供服务

将对象想象为服务提供者。程序本身将向用户提供服务,他讲通过调用其他对象提供的服务来实现这一个目的。
将对象看作是服务提供者的附带好处是:它有助于提高对象的内聚性。高内聚是软件设计的基本质量要求之一:意味着软件构件的各个方面组合的很好。每个对象都可以很好的完成一项任务,但是它并不试图做更多的事。

1.4被隐藏的具体实现

程序开发人员按照角色分为类创建者和客户端程序员。类创建者的目标是构建类,这种类只向客户端程序员暴露必须的部分而隐藏其他部分。如果加以隐藏,客户端程序员将不能够访问它,意味着类创建者可以任意修改被隐藏部分,不用但是对其他人造成任何影响。被隐藏的部分通常代表对象内部脆弱的部分。
访问控制的第一个原因是让客户端程序员无法触及他们不应该触及的部分。
访问控制的第二个原因是允许库设计者可以改变类内部的工作方式而不用担心会影响到客户端程序员。
java有四中访问权限:public、protected、默认、private

1.5复用具体实现

复用某个类的方式就是直接使用该类的一个对象,也可以将那个累的一个对象置于某个新的类中。新的类可以由任意数量,人一类型的其他对象以任意可以实现新的类中想要的功能方式所组成。如果组合是动态发生的,通常被称为聚合。视为”has-a”关系。例如汽车与引擎。
新类的成员对象通常都被声明为private。组合有极大的灵活性,在建立新类时,应该首先考虑组合,它更加简单灵活,再考虑继承。

1.6继承

继承即创建了一个类之后,即使另一个新类与其具有相似的功能,你可以以现有的类为基础,复制它,然后通过添加和修改这个副本来创建新类就好多了。这里写图片描述
类型不仅仅只是描述了一个作用于一个对象集合上的约束条件,同时还有与其他类型之间的关系。两个类型可以有相同的特性和行为,但是其中一个类型可能比另一个含有更多的特性,并且可以处理更多的消息。继承使用基类型和导出类型的概念表示这种类型之间的相似性。一个基类型包含其所有导出类型所共享的特性和行为。
例如基类是几何形,每一个几何形都具有尺寸,颜色,位置等,同时每一个几何形都可以被绘制,擦除,移动和着色等。可以在此基础上,继承出具体的几何形状——圆形,正方形,三角形等。
这里写图片描述

当继承现有类型时,也就创造了新的类型。这个新的类型不仅包括现有类型的所有成员,并且复制了基类的接口。也就是说,所有可以发送给基类对象的消息同时也可以发送给导出类对象。由于通过发送给类的消息的类型可知类的类型,意味着导出类与基类具有相同的类型。“即圆形也是一个几何形”。

如果只是单纯继承一个类而不做其他任何事,那么在基类接口中的方法将会直接继承到导出类,意味着与基类拥有相同的类型与行为,这样做没什么意义。

有两种方法可以使基类与其导出类产生差异。第一种方法:直接在导出类中添加新方法。这些新方法不是基类接口的一部分。第二种方法:改变现有基类方法的行为,称之为覆盖(overriding)

只覆盖基类的方法,这样做二者具有相同的类型和相同的接口,可以用一个导出类对象完全替代一个基类对象。这可以视为纯粹替代,通常称之为替代原则。这种情况下基类与导出类的关系称之为is-a关系,可以说一个圆形是一个几何形状。判断是否继承,就是要确定是否可以用is-a关系描述类之间的关系。
如果在导出类添加了新的接口元素,也就是扩展了接口,这种类型仍然可以替代基类,基类无法访问新的方法,这种情况描述为is-like-a关系。

1.7伴随多态的可互换对象

处理类型的层次结构时,经常想把一个对象不当做它所属的特定类型来对待,而是将其当做其基类的对象来对待。这使得人们可以编写出不依赖于特定类型的代码。在“几何形例子中,方法操作都是”泛化的形状,不关心它们是圆形,正方形,三角形还是其他什么尚未定义的形状。
但是试图将导出类型的对象当作其泛化基类型对象来看待时,仍然存在一个问题。例如让泛化的交通工具行驶,泛化的鸟类飞行,编译器在编译时不知道应该执行哪一段代码:发送这样的消息,程序员并不想知道哪一段代码将被执行;绘图方法可以被等同应用于圆形,正方形,三角形,对象会依据自身具体类型来执行恰当的代码。

为了解决这个问题,面向对象程序设计语言使用了后期绑定的概念。当向对象发送消息时,被调用的代码直到运行时才能确定。编译器确保被调用方法的存在,并对调用的参数和返回值类型检查(无法提供此类保证的语言称为弱类型),但是并不知道将被执行的确切代码。java默认动态绑定,不需要额外关键字来实现多态。

如果用java来编写一个方法:

void doSomething(Shape shape){    shape.erase();    shape.draw();    //.....}

这个方法可以和任何Shape对话,它是独立于任何想要绘制和擦除的对象的具体类型

Circle circle = new Circle();Triangle triangle = new Triangle();Line line = new Line();doSomething(Circle);doSomething(triangle);doSomething(line);

doSomething自动正确的调用,不管对象的确切类型。
将导出类看作是它的基类的过程称为向上转型(upcasting):通常基类在顶部,导出类在其下方散开。
这里写图片描述

1.8单根继承机构

除了C++以外的所有OOP语言,所有的类最终都继承自单一的基类,这个终极基是Object。
单根继承结构中所有对象都具有一个共用接口,单根继承机构保证所有对象都具备某些功能,可以在每个对象上执行基本操作。单根继承结构使得回收器的实现变得容易了多。由于所有对象都保证具有其类型信息,因此不会因无法确定对象的类型而陷入僵局,对于系统级操作尤为重要。

1.9容器

如果不知道解决某个特定问题需要多少个对象,或者它们将存活多久,那么就不知道如何存储这些对象。对于面向对象设计中的大多数问题,这个问题的解决方案似乎过于轻率:创建另一种对象,这种新的对象类型持有对其他对象的引用。这个被称为容器的新对象在任何需要时都可以 扩充自己以容纳你置于其中的所有东西。因此不需要知道将来会把多少个对象置于容器中,只需要创建一个容器对象,然后让它处理所有细节。
虽然单一类型的容器可以满足所有操作,但是还是需要对容器有所选择,这有两个原因。第一:不同容器提供了不同类型的接口和外部行为。堆栈相比于队列就具备不同的接口和行为,也不同于集合和列表的接口和行为,它们之中某种容器提供的解决方案可能比其他容器灵活的多。第二,不同容器对于某些操作具有不同的效率。

1.9.1参数化类型

单根继承机构意味着所有的对象都是object类型,所以可以存储object的容器可以存储任何东西,导致容器很容易被复用。

解决这个问题可以运用到转型,不过这里是向下转型,转型为更为具体的类型。向上转型是安全的,circle是一种Shape类型,但是不知道某个Object是circle还是shape,除非确切知道所要处理的对象类型。

向下转型和运行时检查需要额外的程序运行时间,这里可以映参数化类型机制的解决方案:参数化类型就是一个编译器可以自动定制作用于特定类型上的类。
例如:

ArrayList<Shape>shapes = new ArrayList<Shape>();

1.10对象的创建和生命周期

使用对象,最关键的问题之一就是它们的生成和销毁的方式,每个对象为了生存都需要资源,尤其是内存,不再需要一个对象时,它必须被清理掉,使其占用的资源可以被释放和重用。

java采用动态内存分配方式,即在称为堆的内存池中动态地创建对象。在这种方式,直到运行时才知道需要多少对象,它们的生命周期如何,以及它们的具体类型是什么、。每当想要创建新对象时,就要使用new关键字来构建此对象的动态实例。

在堆上创建对象,编译器对它的生命周期一无所知。java提供了垃圾回收器机制,它可以自动发现对象何时不再被使用,并继而销毁它。

1.11异常处理

自从编程语言问世以来,错误处理就始终是最困难的问题之一。java一开始就内置了异常处理,并且你必须使用它。异常处理将错误处理直接置于编程中,。异常是一种对象,它从出错地点被抛出,并被专门设计用来处理特定类型错误的相应的异常处理器“捕获”。异常提供了一种从错误状态进行可靠恢复的途径。

1.12并发编程

程序中,彼此独立运行的部分称之为线程,多个独立运行的部分称之为“并发”。并发看起来简单,但是有个隐患:共享资源。如果有多个并发任务都要访问同一项资源,那么就会出问题。例如两个进程不能同时向一台打印机发送信息,为了解决这一问题,可以共享的资源,必须在使用期间被锁定,整个过程为:某个任务锁定某项资源,完成其任务,然后释放资源锁,使其它任务可以使用这项资源。

1.13Java与Internet

java对于解决传统的单机程序设计问题非常有用,同样重要的是它解决了万维网上的程序设计问题。
……