Aristotle可能是第一个认真研究类型的概念的,他曾经提出过“鱼的类型和鸟的类型”。所有的对象都是独一无二的,同时,对象也是一类拥有共同特征和行为的对象中的一部分,这个概念是第一个面向对象的语言——Simula-67直接使用的,这个语言基本的关键字class在程序中引入新的类型。
Simula,正如其名,是为了开发诸如经典的“银行行员问题”这一类仿真程序而创造的。这种场景下,有很多“对象”,如行员、顾客、账户、交易及货币单位。在程序执行期间具有不同状态而其他地方十分相似的对象都会被分组到对象的类中,这也是关键字class的来源。创建抽象的数据类型(类)是面向对象编程中的基本概念。抽象数据类型的运行方式与内置类型基本相似:你可以创建类型的变量(在面向对象语法中称为对象或实例),并且可以操作这些变量(称之为发送消息或请求,你给对象发送一个消息,然后对象就会怎么处理这个变量)。每个类的成员(元素)拥有一些共同点:每个账户都有余额,每个行员都可以接受存款等。同时,每个成员也有自己的状态:每个账户的余额是不同的,每个行员都有自己的名字。因此,行员、顾客、账户、交易等都可以在电脑编程中用一个唯一的实体来表示。这个实体是对象,而且每个对象都属于一个特定的类,这个类定义了对象的特征和行为。
因此,尽管我们在面向对象编程中真正要做的是创建新的数据类型,事实上,所有的面向对象编程语言都使用“class”这个关键字。当你看到“type”时,可以把它当做“class”,反之亦然。
由于类描述了一系列拥有完全相同特征(数据元素)和行为(功能)的对象,因此类实际上也是一个数据类型,因为以浮点数举例来说,它也有一系列的特征和行为。其中的不同是程序员为了解决问题定义了类,而不是被迫使用为表示机器中存储而设计的已存的数据类型。你可以为了满足需要创建新的数据类型来丰富编程语言。编程系统欣然接受新的类,并给予和内置类型一样的管护和类型检查。
面向对象方法不仅仅可以创建仿真程序,不管你是否同意,任何程序都是你设计的系统的仿真程序,而采用OOP技术可以轻易的减少仿真程序的很多问题。
一旦类被创建完成,你可以尽你所需来创建这个类的对象,而且可以操作这些对象,正如这些对象就是你要解决的问题中的元素一样。的确,面向对象编程面临的挑战之一是建立问题空间中的元素与解决空间中的对象之间的一对一映射。
但是怎么获取一个对你有用的对象呢?需要有这么一个方式来对对象发送请求,使对象可以做一些事情,如完成一笔交易,在屏幕上画一些东西,或者是打开一个开关。并且每个对象只能满足唯一确定的请求。可以对对象发送的请求是由对象的接口定义的,决定接口的便是类型。以电灯泡为例来做一个简单的比喻:
Light lt = new Light();
Lt.on();
接口决定了你可以对一个特定的对象发送什么样的请求,然而,必须有一段代码来满足你的请求。这样,与隐藏的数据一起构成了实现。从编程实现上来看,这并不复杂。每个类型都有一个可以与每一个可能的请求相关联的方法,当你对一个对象发出特定请求是,这个方法就会被调用。这个过程通常被总结为你对对象“发送消息”,然后这个对象会知道怎么处理这个消息(执行代码)。
这个例子中,类型/类的名字是Light,特定的Light对象的名字是lt,你向这个Light对象发送的请求是开灯、关灯、更亮一些或者更暗一些。你通过定义一个“引用”(lt)来建立Light对象,通过调用new这个关键字来请求这个类的一个新的对象。为了向这个对象发送消息,你声明了对象名称并且以圆点来连接这个消息请求。从预定义类的用户的观点来看,这基本上就是用对象来编程的全部内容。
前面的图示遵循Unified Modeling Language(UML)格式。使用一个方框表示类,类名在方框的上半部分,你关心的数据成员在方框的中间部分,方法(对象用来接收你发出的任何消息的方法)在方框的下半部分。通常来说,只有类名和公共方法在UML设计图中展示出来,所以在这个例子中,中间部分没有展示。同理,如果你只关心类名的话,方框的下半部分也不需要展示出来。