本节书摘来自华章出版社《面向对象的思考过程(原书第4版)》一书中的第1章,第1.5节,[美] 马特·魏斯费尔德(Matt Weisfeld) 著黄博文 译更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1.5 究竟什么是对象
对象是面向对象程序中的基础材料。使用面向对象技术的程序本质上是对象的集合。举例来说,一个公司系统包含了代表公司雇员的对象。接下来的小节描述了这些对象的数据和行为。
1.5.1 对象数据
存放在对象中的数据代表了该对象的状态。在面向对象术语中,数据被称为属性。在图1-6的例子中,雇员的属性可以是社会安全号码、生日、性别、电话号码等。属性包含的信息将不同对象区分开来,在本例中是把不同的雇员区分出来。本章中讨论类时会讲述属性的细节。
1.5.2 对象行为
对象的行为表示对象可以做什么。在过程式语言中,可以通过过程、函数及子程序定义行为。在面向对象程序设计术语中,这些行为包含在方法中,你可以通过发送消息的方式来调用方法。在雇员例子中,考虑到雇员对象需要的行为之一是对属性值进行存取,所以每个属性会有相应的方法,比如setGender()和getGender()。当另一个对象需要该信息时,可以给雇员对象发送一个消息来询问其性别。
毫不奇怪,在本书第1版发布时,应用程序中已经出现了取值方法(getter)和赋值方法(setter),当然还有很多其他的面向对象技术。而且很多技术都与数据相关。通过第11章及第12章,我们可以看到如何使用面向对象的方式组织数据。使用对象最强大、最有趣的一点在于,数据与行为是一个整体,而不是与行为代码割裂。
XML的出现并不全为了以可移植的方式表示数据。它也有一种替代方式来让代码轻松访问数据。在.NET技术中,取值方法和赋值方法都被认为是数据自身的属性。
例如,Java中定义一个名为Name的属性如下所示:
对应的取值方法和赋值方法如下所示:
现在,使用C#.NET定义一个名为Name的XML属性,代码如下所示:
在这种方式中,取值方法和赋值方法实际上是属性Name的属性。
不论采用什么方式,目的都是一致的,即控制对属性的访问。本章中,我想先聚焦于取值方法和赋值方法的概念本质。而在第11章及以后的章节中讲述面向对象数据时会有更多关于属性的知识。
取值方法和赋值方法
取值方法和赋值方法的理念就是数据隐藏。因为其他对象不应该直接操作另一个对象中的数据,而取值方法和赋值方法提供了对对象数据的访问控制。取值方法和赋值方法有时分别被称为访问方法(accessor method)和设值方法(mutator method)。
注意,我们只展示了这些方法的接口,而不是实现。以下几点列出了用户需要知道如何实际使用这些方法:
方法名
传给方法的参数
方法的返回值
请看图1-7演示的行为。
图1-7中,Payroll对象包含了一个名为CalculatePay()的方法,用于计算具体雇员的薪水。Payroll对象需要获取该雇员的社会安全号码。为了获取该信息,Payroll对象需要给Employee对象发送一个消息(本例中即调用getSocialSecurityNumber()方法)。基本上,这意味着Payroll对象调用Employee对象的getSocialSecurityNumber()方法。Employee对象接收到该消息并返回请求的信息。
UML类图
由于这是我们看到的第一个类图,所以进行了一些简化,缺乏一些类应该具有的结构(例如构造函数)。不过没关系,第3章中我们会详细讨论类图及构造函数。
每个类图由三部分组成:类名、数据(属性)、行为(方法)。图1-8中,Employee类图的属性区域包含SocialSecurityNumber、Gender和DateofBirth。方法区域包含了操作这些属性的方法。你可以使用UML建模工具来创建和维护类图以对应真实的代码。
建模工具
可视化建模工具提供了一种方式来使用统一建模语言(unified modeling language,UML)创建和操作类图。对于类图的讨论贯穿本书,第10章会指导如何使用该标记语言。UML类图可以作为一个工具来可视化类以及类与类之间的关系。本书中对UML的使用仅限于类图。
本章稍后会介绍类与对象的关系。但现在你可以认为类是创建对象的模板。当对象被创建时,我们看到对象被实例化。因此,如果我们创建三个雇员,实际上是创建了三个Employee类的直接实例。每个对象都包含了属性和方法的副本。例如,图1-9中,一个叫作John的对象(John是该对象的标识)自身拥有Employee类中所有的属性和方法的副本。叫作Mary的雇员类也拥有自己独立的属性和方法的副本。这两个对象各自拥有DataOfBirth属性和getDateOfBrith方法的副本。
图1-9 程序空间
实现问题
请注意没必要为每个对象的每个方法都实现一个物理副本。其实,每个对象指向了同一个实现。不过这个问题可以交由编译器/操作系统平台来解决。从概念上来说,你可以认为对象是完全独立的,各自拥有独立的属性和方法。