《Java编程思想》第1章 对象导论


面向对象程序设计(Object-oriented Programming, OOP)

1.1 抽象过程

所谓的“类型”是指“所抽象的是什么?”。
面向对象语言的五个基本特性:
1)万物皆为对象。将对象视为奇特的变量,它可以存储数据,除此之外,你还可以要求它在自身上执行操作。理论上讲,你可以抽取待求解问题的任何概念化构件(狗,建筑物,服务等),将其表示为程序中的对象。
2)程序是对象的集合,它们通过发送消息来告知彼此所要的。要想请求一个对象,就必须对该对象发送一条消息。更具体地说,可以把消息想象为对某个特定对象的方法的调用请求。
3)每个对象都有自己的由其他对象所构成的存储。换句话说,可以通过创建包含现有对象的包的方式来创建新类型的对象。因此,可以在在程序中构建复杂的体系,同时将其复杂性隐藏在对象的简单性背后。
4)每个对象都拥有其类型。按照通用的说法,“每个对象都是某个类(class)的一个实例(instance)”,这里“类”就是“类型”的同义词。每个类最重要的区别于其他类的特性就是“可以发送什么样的消息给它”。
5)某一特定类型的所有对象都可以接收同样的消息
一个更加简洁的描述:对象具有状态,行为和标识。这意味着每一个对象都可以拥有内部数据(它们给出了该对象的状态)和方法(它们产生行为),并且每一个对象都可以唯一地与其他对象区分开来,具体说来,就是每一个对象在内存中都有一个唯一的地址。

1.2 每个对象都有一个接口

创建抽象数据类型(类)是面向对象程序设计的基本概念之一。抽象数据类型的运行方法与内置(built-in)类型几乎一致:你可以创建某一类型的变量(按照面向对象的说法,称其为对象实例),然后操作这些变量(称其为发送消息请求;发送消息,对象就知道要做什么)。
因为类描述了具有相同特性(数据元素)和行为(功能)的对象集合,所以一个类实际上就是一个数据类型,例如所有浮点型数字具有相同的特性和行为集合。
每个对象都只能满足某些请求,这些请求由对象的接口(interface)所定义,决定接口的便是类型。以电灯泡为例来做一个简单的比喻(如下图所示):
在这里插入图片描述

Light lt = new Light();
lt.on();

接口确定了对某一特定对象所能发出的请求。但是,在程序中必须有满足这些请求的代码。这些代码与隐藏的数据一起构成了实现。
上例中,类型/类的名称是Light,特定的Light对象的名称是lt,可以向Light对象发出的请求是:打开它、关闭它、将它调亮、将它调暗。

1.3 每个对象都提供服务

将对象想象为“服务的提供者”。

1.4 被隐藏的具体实现

将程序开发成员按照角色分为类创建者(那些创建新数据类型的程序员)和客户端程序员(那些在其应用中使用数据类的类消费者)。
访问控制的第一个存在原因就是让客户端程序员无法触及他们不应该触及的部分——这些部分对数据类型的内部操作来说是必需的,但不是用户解决特定问题所需的接口的一部分。这对客户端程序员来说其实是一项服务,因为它们可以很容易的看出那些东西对他们来说很重要,而那些东西可以忽略。
访问控制的第二个存在原因就是允许库设计者可以改变类内部工作方式而不担心会影响到客户端程序员。

1.5 复用具体实现

组合(composition)。
实际上,在建立新类时,应该首先考虑组合,因为它更加简单灵活。

1.6 继承

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

1.7 伴随多态的可互换对象

在处理类型的层次结构时,经常想把一个对象不当作它所属的特定类型来对待,而是将其当作其基类的对象来对待。这使得人们可以编写出不依赖与特定类型的代码。在“几何形”的例子中,方法操作的都是泛化(generic)的形状,而不关心它们是圆形、正方形、三角形还是其他的什么尚未定义的形状。所有的几何形状都可以被绘制、擦除和移动,所以这些方法都是直接对一个几何形对象发送消息;它们不用担心对象将如何处理消息。
在这里插入图片描述
在下面的图中,BirdController对象仅仅处理泛化的Bird对象,而不了解它们的确切类型。从BirdController的角度看,这么做非常方便,因为不需要编写特别的代码来判定要处理的Bird对象的确切类型或其行为。当move()方法被调用时,即便忽略Bird的具体类型,也会产生正确的行为(Goose(鹅)走、飞或游泳 ,Penguin(企鹅)走或游泳)),那么,这是如何发生的呢?
在这里插入图片描述
为了解决这个问题,面向对象程序设计语言使用了后期绑定的概念。当向对象发送消息时,被调用的代码直到运行时才能确定。编译器确保被调用方法的存在,并对调用参数和返回值执行类型检查,但是并不知道将被执行的确切代码。
把将导出类看做是它的基类的过程称为向上转型(upcasting)。
在这里插入图片描述

1.8 单根继承结构

所有的类都继承自单一的基类。

后面待补。。。

猜你喜欢

转载自blog.csdn.net/lanzijingshizi/article/details/83903527