3.1 从数据开始
语言程序是进行数据处理的。有什么样的数据以及对数据进行什么样的处理,决定了程序怎么写,与此同时对选择什么样的语言进行开发也提出了要求。
3.1.1 类的角色
本章是承前启后的一章。本章的意图是给读者一个渐进的台阶,先蜻蜓点水、泛泛而论面向对象,了解一些名词术语和基础知识,尽管可能不求甚解。然后再进入面向对象的世界里使用洪荒之力。这样避免读者直接接触面向对象复杂的语法而头昏脑胀。经验表明这种情况很常见。
关于类,学过前面两章,我们知道它是Java程序的外壳。在这个壳里面定义一个或多个方法,其中有一个main方法(对Java applications而言),程序执行从main方法开始,也在main方法结束,执行期间可能调用其他方法。
好的,我们再看一看这个熟悉的结构:
class Concrete Name{ // Concrete Name是椰子壳
public static void main(String[] args){ //椰汁
//write your code //椰汁
}
}
一个问题是:类仅仅是个程序代码的外壳吗?像椰子壳?人们喝的是外壳包藏着的甜蜜的椰汁,那个生硬的外壳是个没价值的东西?
并非如此。我们不久将发现:类中可以封装丰富的内容,它代表着一类事物。我们的程序中可以有不止一个类,类和类之间相互关联着,就像现实世界中诸多的事物相互关联着一样。
3.1.2 事物数据化
今日世界已经进入信息化时代。各行各业都在使用计算机管理各种数据信息。在电子商务系统中,商品信息描述为如表3-1所列的数据。
表3-1 商品信息表
在学校的教务管理系统中,你会看到如表3-2所列的数据。
表3-2 教师信息表
在图书管理系统中,书籍信息数据以表3-3形式存储。
表3-3 图书信息表
这样的例子数不胜数。
这些表中存储的是各种类型的数据,它们表示了不同的事物,即商品、教师和图书。表的每一列表示事物的一个属性,例如图书的书号、编者、定价等。这些不同列既可能是数值型的,可能是日期型的,可能是字符串的,也可能是其他的类型。
表中的一行数据表示具体的一种商品如一双Li-Ning牌运动鞋、一名教师如栾小晨、一本书如《计算机网络》。
为了区别于那些基本类型的数据,我们把这些代表某种事物的“复杂”数据称为对象。
对象数据大量出现在程序中,当然是计算机应用领域拓展到事物管理阶段的结果。
为什么面向对象的语言如Simula-67和Smalltalk在20世纪60年代即推出,但是面向对象语言和面向对象成为主流软件开发工具和开发方法却是在90年代。在60年代软件危机出现时,面向过程的结构化语言应运而生,其中最具代表性的语言包括Pascal、C语言等。其后在80年代和90年代,计算机的微型化和网络化使之从束之高阁到走入寻常百姓家,计算机应用迅速普及,应用领域也迅速拓展。大量的事务管理数据处理需求导致软件规模迅速膨胀,要求语言安全、高效、易于维护软件。这使得一批新的面向对象语言登堂入室,被广大学习者和开发者青睐,其中的典型语言包括Java、C++等。
拓展知识
Smalltalk被公认为历史上第二个面向对象的程序设计语言和第一个真正的集成开发环境 (IDE)。由Alan Kay,Dan Ingalls,Ted Kaehler,Adele Goldberg等于20世纪70年代初在Xerox PARC开发。Smalltalk对其他众多的程序设计语言的产生起到了极大的推动作用,主要有Objective-C,Actor,Java 和Ruby等。90年代的许多软件开发思想得利于Smalltalk,例如设计模式、极限编程和重构等。
3.1.3 对象的特殊性
对象不同于基本类型数据,它们有什么特殊性呢?
首先我们发现,对象没有现成的类型可用,需要自己动手定义。就是说,数据都有个类型,1、2、3是整型数,int用于定义整型变量;“a”“b”“c”是字符型数,char用于定义字符型变量;“true”“false”是布尔型数,布尔型变量用boolean定义。张三、李四这两个对象是什么类型的,怎么定义他们的类型?
这就回到了本章开头的问题,类名不是简单的没有意义的“椰子壳”,它意味着很多。我们需要用class来定义一个类,这个类就是类型。假如张三、李四的类型是学生,那就需要定义学生类Student。在类中需要说明这类事物有哪些属性,属性可以列举许多,在系统中根据需要进行选择。
class Student{ //对象的类
…… //对象的属性
…… //对象的行为
}
对象的特殊性还在于,不同的对象对应不同的操作(处理),比如说学生可能会注册、选课,正如数值有加减乘除取余操作。基本类型的操作,在Java语言中用算符完成。而对象的操作需要自己定义。定义哪些操作?在哪里定义?这些都是必须做的事。
图3-1 基本类型与对象
关于对象有另一个问题:既然万事万物皆为对象,1、2、3、'a'、'b'、'c'不是事物?它们不是对象?
这是个值得思考的问题。事实上,确实有的语言例如Ruby把一切数据都作为对象看待, 1、2、3、'a'、'b'、'c'在Ruby中也是对象。但是,Java不是这样。Java中有了基本类型int、char、float、double等,用它们定义那些基本类型的数据。Java似乎把基本类型数据排斥在万事万物之外了,分类示意如图3-1所示。Java和Ruby在这一点孰是孰非,读者将来可以给出判断。
总之,Java把那些复杂的事物数据,称为对象。
这里已经不可避免地提到了类,我们马上把目光移向它。
3.1.4 对象分类
俗话说,物以类聚。在对象数量很多的情况下,需要对其分类。表3-1~表3-3,表示的是不同的事物类型,因为每个表的属性名与其他表不同。对象为什么要分类?
想象一下:在一个大型电子商务网站,网站单日销售额可达几十亿甚至几百亿元,销售的商品数量特别大,这意味着需要管理的数据可能是海量的。那么,海量的商品信息如何保存呢?需要考虑的问题主要有两个:首先是对商品分类,然后是确定商品的属性信息。某网站显示其商品种类的方式如图3-2所示。
图3-2 某电商网站商品分类
客户在网上购物的时候,首先确定买哪类商品,首先需要在分类列表中选择一个类别,例如要买笔记本计算机,就选择计算机、办公类。然后再按照价格、屏幕尺寸、处理器种类等商品属性进行选择,如图3-3所示。
对象分类是为了管理方便。分类存储,分类显示,按属性进行查询和显示,用户选择操作简单快捷。正如在超市里,琳琅满目的商品如果不分区分类地摆放在货架上,大家去超市购物势必像大海捞针一样费力,如果那样,谁还愿意逛超市?谁还能轻松购物呢?
对象分类的依据是它们的属性。一类事物与其他类事物不同,是由于不同事物类有着不同的属性。
对象什么样,谁来说明?用类来说明,类就是类型。例如int规定了它定义的变量的大小,一个类规定了它定义的对象具有哪些属性以及可以进行哪些操作,因此说类就是类型。一个类是一些对象的代表,用这个类定义的对象则是类的具体实例。
图3-3 按商品属性选择
现实生活中的对象分类是我们习以为常的。在Java程序中的类设计与此相对应。类设计首要的任务就是关注它具有哪些属性。
3.1.5 对象处理
对象处理
程序是要处理数据的。问题本身决定了进行什么处理。比如教师提交的学生成绩,按要求应该把平时成绩和期末考试成绩按比例折算出总成绩,还要把分数按照公式折合成绩点(Grade Point Average,GPA),然后按绩点从高到低排序,作为评奖学金或保送研究生的依据。
对象的数据处理,也是根据程序的任务,以及要解决的问题的需要,确定定义哪些方法(method)。对象的处理方法也和属性一样,往往是对象独有的。例如平面几何图形类对象有计算面积和周长的需求,可能需要定义area()和perimeter()方法。但是对于立体类对象,往往需要计算体积,那就需要定义volume()方法了。
再比如,在学校的管理系统中,学生类Student对象,可能要定义注册、交学费、选课等方法,而教师则有提交教学材料、提交成绩等方法。
不同类的对象也会用相同的操作,参见例3.1可知。但是,重点关注的应该是不同的操作。
看下面的例子,可以关注一下类中定义的属性和方法有哪些?概要了解类定义和对象定义的关系。语法细则在此不必深究。
【例3.1】定义圆、矩形和三角形类,观察边长相等情况下哪种图形的面积最大。
【分析】试图用这个例子说明,一个程序可以定义多个类,类中可以定义数据和方法,用方法可以处理数据。对代码做到理解要旨,不求甚解即可。要比较周长为18的3个图形的面积,假设圆的半径为18 /(2×3.14)=2.866、矩形的宽(width)和高(height)分别为5和4、三角形三边均为6。
【代码】
class Circle
{
double x, y, r;//圆的位置坐标、半径
Circle(double x1,double y1,double r1) //构造方法,为对象属性x,y,r赋初值的
{
x = x1;
y = y1;
r = r1;
}
double area() //计算圆面积方法
{
return 3.14*r*r;
}
}
class Rectangle
{
double width, height;//矩形长、宽
Rectangle(double a, double b)
{
width = a;
height = b;
}
double area() //计算矩形面积方法
{
return width*height;
}
}
class Triangle
{
double a, b, c;//三角形三条边
Triangle(double a1,double b1,double c1)
{
a = a1;
b = b1;
c = c1;
}
double area() //计算三角形面积方法
{
double s = (a + b + c)/2;
//用海伦公式求三角形面积,sqrt()是计算平方根的方法
return Math.sqrt(s*(s-a)*(s-b)*(s-c));
}
}
public class Example3_1
{
public static void main(String[] para)
{
Circle c = new Circle(100,50,2.866);//定义一个圆类对象
Rectangle rect = new Rectangle(5,4);//定义一个矩形对象
Triangle tr = new Triangle(6,6,6);//定义一个三角形对象
System.out.println("The area of the circle is: "+c.area());
System.out.println("The area of the rectangle is: "+rect.area());
System.out.println("The area of the triangle is: "+tr.area());
}
}
程序运行结果如图3-4所示。
图3-4 例3.1程序运行结果