《Java开发 - 第2部分 面向对象》第1章 类和对象

1.1从过程式编程到面向对象编程

1.1.1过程式程序设计(LISP)

过程式编程只是一系列为了实现需求功能的特定步骤的命令集合。LISP是一种通用高级计算机程序语言,长期以来垄断人工智能领域的应用。LISP作为因应人工智能而设计的语言,是第一个声明式系内函数式程序设计语言,有别于命令式系内过程式的C、Fortran和面向对象的Java、C#等结构化程序设计语言。

LISP名称源自列表处理(LISt Processing)的英语缩写,由来自麻省理工学院的人工智能研究先驱约翰·麦卡锡(John McCarthy)在1958年基于λ演算所创造,采用抽象数据列表与递归作符号演算来衍生人工智能。

1.1.2 结构化程序设计(C)

结构化编程引入了函数,程序块等概念,改善计算机程序的明晰性。 结构化程序设计方法主张按功能来分析系统需求,其主要原则可概括为自顶向下,逐步求精,模块化等。结构化程序设计首先采用结构化分析(Structrued Analysis,即SA)方法对系统进行需求分析,然后使用结构化设计(Structrued Design,即SD)方法对系统进行概要设计、详细设计,最后采用结构化编程(StructruedProgram,即SP)方式来实现系统。使用这种SA、SD和SP的方式可以较好的保证软件系统的开发进度和质量。

结构化程序设计方法主张按功能把软件系统逐步细分,因此这种方法也被成为面向功能的程序设计方法;结构化程序设计的每个功能都负责对数据进行一次处理,每个功能都接受一些数据,处理完后输出一些数据,这种处理方式也被称为面向数据流的处理方式。

在这里插入图片描述

图1

 结构化程序设计的局限性

 设计不够直观,与人类习惯思维不一致。采用结构化程序分析、设计时,开发者需要将客观世界模型分解成一个。一个功能,每个功能用以完成一定的数据处理。
 适应性差,可扩展性不强。由于结构化设计采用自顶而下的设计方式,所以当用户的需求发生改变,或需要修改现有的实现方式时都需要自顶而下地修改模块结构,这种方式的维护成本相当大。

 程序的三种结构

结构化程序设计非常强调实现某个功能的算法,而算法的实现过程是由一系列操作组成的,这些操作之间的执行次序就是程序的控制结构。1996年,计算机科学家Bohm和Jacopini证明了这样的事实:任何简单或复杂的算法都可以由三种结构组成

 顺序结构
 选择结构
 循环结构这

这三种结构就被称为程序设计的三种基本结构,也是结构化程序设计必须采用的结构。

1.1.3 面向对象程序设计(C++/Java)

面向对象是一种更优秀的的程序设计方法,它的基本思想是使用类、对象、继承、封装,消息等基本概念来进行程序设计。它是从现实世界中客观存在的事物(即对象)出发来构造软件系统,并在系统构造中尽可能运用人类的自然思维方式,强调直接以现实世界中的事物(即对象)为中心来思考问题,认识问题,并根据这些事物的本质特点,把它们抽象地表示为系统中的类,作为系统的基本构成单元(而不是用一些与现实世界中的事物相关比较远,并且没有对应关系的其它过程来构造系统),这使得系统可以直接映射客观世界,并保持客观世界中事物及其相互关系的本来面貌。

如果采用面向对象方式开发的软件系统,其最小的程序单元是类,这些类可以生成系统中的多个对象,而这些对象则直接映射成客观世界的各种事物。

 面向对象的特征

面向对象方法具有三个基本特征:继承(Inheritance)、封装(Encapsulation)和多态(Polymorphism)。
面向对象还支持如下几个功能:
对象是面向对象方法中最基本的概念,它的基本特点有:标识惟一性、分类性、多态性、封装性、模块独立性好。

是具有共同属性、共同方法的对象的集合。类是对象的抽象;对象则是类的实例。而类是整个软件系统最小的程序单元,类的封装性将各种信息细节隐藏起来,并通过公用方法来暴露该类对外所提供的功能,从而提高了类的内聚性,降低了对象之间的耦合性。

对象间的这种相互合作需要一个机制协助进行,这样的机制称为“消息”。消息是一个实例与另一个实例之间传递的信息。

在面向对象方法中,类之间共享属性和操作的机制称为继承。已有的类可当作基类来引用,则新类相应地可当作派生类来引用。继承具有传递性。可分为单继承(一个继承只允许有一个直接父类,即类等级为树形结构)与多继承(一个类允许有多个直接父类)。

1.1.4 过程式编程、结构化编程与面向对象编程的比较

举例,用三种编程方式实现1+2+3…+100的计算

过程式编程

int total = 0;
for(int i = 1; i <= 100; i ++) {
	total += i;
}

结构化编程

private int add(int a, int b) {
	return a + b;
}
int total = 0;
total = 100 / 2 * add(1, 100);

面向对象编程

public class Sum {
	int from = 0;
	int to = 0;
	public Sum(int a, int b) {
		from = a;
		to = b;
	}
	private int add(int a, int b) {
		return a + b;
	}
	public int getTotal() {
		int total = 0;
		total = (to - from + 1) / 2 * add(from, to) + (to - from + 1) % 2 * ((to - from) / 2 + from);
	}
}
Sum mSum = new Sum(1, 100);
mSum.getTotal();

好了,总结下,面向对象和面向过程的思想有着本质上的区别,作为面向对象的思维来说,当你拿到一个问题时,你分析这个问题不再是第一步先做什么,第二步再做什么,这是面向过程的思维,你应该分析这个问题里面有哪些类和对象,这是第一点,然后再分析这些类和对象应该具有哪些属性和方法。这是第二点。最后分析类和类之间具体有什么关系,这是第三点。面向对象有一个非常重要的设计思维:合适的方法应该出现在合适的类里面。

面向对象的基本思想是,从现实世界中客观存在的事物出发来构造软件系统,并在系统的构造中尽可能运用人类的自然思维方式。面向对象更加强调运用人类在日常生活的逻辑思维中经常采用的思想方法与原则,如抽象、分类,继承、聚合、多态等。人在思考的时候,首先眼睛里看到的是一个一个的对象。

1.2类

1.2.1定义

对象是用于计算机语言对问题域中事物的描述,对象通过“属性(attribute)”和“方法(method)”来分别对应事物所具有的静态属性和动态属性。类是用于描述同一类的对象的一个抽象的概念,类中定义了这一类对象所具有的静态属性和动态属性。类可以看成一类对象的模板,对象可以看成该类的一个具体实例。

eg.什么叫瓶子?
瓶子的定义:具有某些类特征的东西就是瓶子,比分说什么样的形状,比方说有个口,能倒水,能装水,一般有个盖等等。给瓶子下定义的过程,其实就是把瓶子里的某些东西抽象出来了,所以瓶子在这里是叫做一类事物的一个抽象,在你脑子里有瓶子的概念,可瓶子的概念在你脑子里到底是什么呢?瓶子的概念在你脑子里叫做一类事物的一个抽象。怎么抽象的呢?你往往抽象的是这两个方面:第一个方面我们叫它静态的属性,瓶子应该具有哪些特征,比分说瓶子应有个口,这是它的具有的一个静态属性,瓶子一般有一个盖,这也是它的具有一个静态属性,除此之外,你还可能给它总结动态的属性,什么动态的属性呢?比放说瓶子能倒水,这是它的动态属性。瓶子这个概念在你脑子里如果你细细的思维的话,其实你给它做了两方面的总结,一方面是静态的,一方面是动态的。反映到JAVA的类上,一个就是成员变量(静态属性),一个就是方法(动态属性)方法是可以执行的,可以动的。成员变量是某一个类的静态属性。所以你脑子里瓶子的概念实际上是一类事物的一个抽象,这种东西我们叫它类,椅子是类,桌子是类,学生是类。什么是对象呢?这一类事物的具体的某个实例就叫做对象。所以一类事物的具体的某一个东西,符合这类事物具体的特征的某个东西就叫做对象。瓶子是一个类,某个瓶子就是瓶子这个类里面的一个对象。

类定义:类是同一类对象的属性和行为的抽象;类描述同一类对象应该包括的属性;类描述同一类对象所共有的行为特征。

对象定义:使用 new 关键字或反射技术创建的某个类的实例。同一个类的所有对象,都具有相似的数据(比如人的年龄、性别)和行为(比如人的吃饭、睡觉),但是每个对象都保存着自己独特的状态,对象状态会随着程序的运行而发生改变,需要注意状态的变化必须通过调用方法来改变,这就是封装的基本原则。
如何抽象出一个类?有两个方面,一方面是它的静态属性,另一方面是它的动态属性。反映到JAVA里面的类怎么包装它呢?一方面成员变量,另一方面是方法。
eg.职员这个类该怎么抽象出来?也是从两个方面,一方面是它的静态属性,另一方面它的动态属性。职员有哪些属性呢?有姓名,年龄,目前工资数额等属性,他有哪些方法呢?让这个职员来显示姓名,显示年龄,修改姓名,领取工资。当然显示姓名,显示年龄,修改姓名,领取工资这些也可以让别人来做,但面向对象的设计思维是最合适的方法应该出现在最合适的类里面。显示姓名,显示年龄,修改姓名,领取工资由谁来做更合适呢,那就是职员自己最合适。所以这些方法应该出现在职员这个类里面。

在这里插入图片描述

图2

对于类来说,它有一些属性或者称为成员变量,以后说属性或者成员变量指的是同一回事。具体的对象他有没有相关的一些属性或者叫成员变量呢?有,每一个人都有一份,只不过是取值不同而已。如从职员这个类实例化出来的两个职员:职员A和职员B,他们都有姓名,年龄,目前工资数额这些属性,但他们的名字,年龄,领取的工资数额都不一样。这样就能把职员A和职员B区分开来了,正是因为他们的属性值不一样,所以这个对象才能和另外的对象区分开来,所以通过属性是可以区分两个对象的。猫是一个类,这只猫是一个对象,这只猫和另外一只猫该怎么区分开来呢?那就得看你的猫这个类是怎么定义的了,猫有猫毛,毛有颜色。OK,这只猫是黑猫,另一只猫是白猫,这样通过猫毛的颜色区分开来了。如果只定义一个,如捉老鼠,白猫也能捉,黑猫也能捉,这样就没办法区分出黑猫和白猫了,所以根据方法是没办法区分两个对象的。所以每个对象都有自己的属性,属性值和另外一个对象一般是不一样的。

1.2.2类(对象)之间的关系

1.关联关系(最弱的一种关系)

在这里插入图片描述

图3

类和类之间是有关系的,如学生和老师这两个类,老师可以教学生,学生可以向老师学习。这就是他们之间的关系。关系和关系之间是不同的,你和你老婆的关系和你和你其他女朋友的关系是不能混为一谈的。关系最弱的一种关系叫关联关系。关联关系反应到代码上往往是一个类的方法里面的参数是另一个类的具体的某一个对象,比如教授教研究生,教哪个研究生,教是教授这个类里面的一个方法,某个研究生是研究生这个类里面的一个具体的对象。关联关系是最弱的一种关系,咱们两个类之间有关系,或者两个对象之间有关系,但关系不是很紧密。

2.继承关系(比较强的一种关系)
继承关系(一般和特殊)

在这里插入图片描述

图4

继承关系封装了这样一种逻辑:“XX是一种XX”,只要这东西能说通了,就可以考虑用继承关系来封装它。
如:游泳运动员从运动员继承,游泳运动员是一种运动员,这能说得通,所以游泳运动员就是从运动员继承过来的,游泳运动员和运动员就是一种继承关系。学生是一个人,学生从人继承,老师是一个人,老师也从人继承,学生是一种老师,这说不通,所以学生和老师就不存在继承关系。所以将来做设计的时候要分清继承关系很简单,你只要说通这么一句话:“XX是一种XX”。OK,那他们之间就是继承关系。篮球运动员是一种球类运动员,这说得通,所以篮球运动员从球类运动员继承,这样继承很有可能会产生一棵继承树,运动员派生出来,派生出来的意思是游泳运动员这个类、球类运动员这个类、射击运动员类从它继承,相当于运动员派生出来了这些个不同的运动员,包括游泳的,球类的,射击的。球类的再派生足球的,篮球的,排球的。这就是一棵继承树,不过这棵树是比较理想化的情况,只有一个根节点。但实际当中,我们真实世界当中的继承关系不一定只从一个类继承,一个类可能从多个类继承过来,比如说:金丝猴从动物这个类继承,这很正常,但我还有另外一个专门的类:“应该受到保护的东西”,这也是一个类,金丝猴应该受到保护,所以金丝猴是一种应该受到保护的东西。所以金丝猴从“应该受到保护的东西”这个类继承过来。所以在现实情况当中,一个类完完全全有可能从多个不同的类继承,C++正是因为想封装这种继承关系,所以C++存在多重继承。

3.聚合关系(整体和部分)(比较强的一种关系)

在这里插入图片描述

图5

什么是聚合?聚合就是一个整体与部分的关系。我们说“XX是XX的一部分”,只要说得通,那么他们之间的关系就是聚合关系,队长是球队的一部分,队员是球队的一部分。所以队长和球队是聚合关系,队员和球队也是聚合关系。脑袋是人的以部分,身体和胳膊也是人的一部分,因此脑袋,身体和胳膊与人都是聚合关系。 聚合关系分得再细一点的话就可以分成聚集关系和组合关系 ,比如球队、队长,队员,这三者是聚集关系,假如这个队长既是足球的队长,同时也是篮球的队长,一个人分属两个不同的球队,这是可以的,球队与队长之间没有我离不了你,你离不了我这种情况,所以如果分得更细的话,这种就叫做聚集关系。还有一种情况叫组合,组合说的是咱们俩密不可分,我是你必不可少的一部分。一个人的脑袋不可能既属于你又属于别人,身体也一样,不可能既属于你又属于别人。所以你的身体,脑袋和你是密不可分的,这是一种更加严格的聚合关系,专门给它取了个名字叫组合。

4.实现关系

在这里插入图片描述

图6

作为父类来说,我觉得我应该具有这样一个方法,但我不知道怎么去实现,谁去实现,我的子类去实现,这就是实现关系。和实现关系息息相关的还有一种关系叫多态。

5.多态

在这里插入图片描述

图7

1.2.3 Java语言创建类

[修饰符] class <类名> {
	[成员变量定义]
	[构造器]
	[成员方法定义]
} (“[]”表示可有可无,“<>”表示必须有)
public class Student{
	//变量
	public int age;
	public int id;
public String name;

	//构造器
	public Student(){};

	//方法
	public void study(){};
public void sleep(){};
}

修饰符:可为public,protected,default,private用来指定被修饰项的被访问权限。

 成员变量定义
[修饰符] <数据类型> <变量名> [=默认值] ;
注意:如果没有设置修饰符,默认使用default修饰;以分号结尾;如果不设置默认值,使用系统默认值(不同数据类型的默认值不同)

 构造器
[修饰符] <类名> ([参数列表]){[代码]}
注意:如果没有设置修饰符,默认使用default修饰。一定要使用类名作为构造器的名字。参数列表可有可无。每一个类都会有构造器,如果没有设置构造器,该类默认使用系统默认的无参构造器。

 成员方法定义
[修饰符] <返回数据类型> <方法名> ([参数列表]){[代码]}
注意:如果没有设置修饰符,默认使用default修饰。如果行为没有返回值,需将返回数据类型设置为void,参数列表可有可无。

1.3 Java源文件的基本结构

1.3.1 基本结构

package <所处包>
import <需要引入的其他包>
<public类>

类中包含:属性(变量),行为(方法),构造器

注意:
使用package <包名>的方式定义所处包。使用import <包名>的方式引入其他包。
一个java应用程序的源文件可以包含多个类。一个源文件中如果有多个类,只有一个使用public修饰的类,并且java源文件名必须与public类名相同。如果源文件中没有public类,那么源文件的名字只要和某个类的名字相同。一个java应用程序,必须有一个类含有:public static void main( String arg[])方法,称这个方法为主函数,称这个类是应用程序的主类。

1.3.2 对象

定义: 对象是类的实体。对象是实现面向对象编程的主体(程序由对象构成)。对象具有明确的属性和行为。方法和变量必须在对象创建之后才可以使用。对象是类的一个实例,创建对象的过程也叫类的实例化。对象是以类为模板来创建的。

在Java中,使用new关键字来创建对象,一般有以下三个步骤:

 声明:声明一个对象,包括对象名称和对象类型。
 实例化:使用关键字new来创建一个对象。
 初始化:使用new创建对象时,会调用构造方法初始化对象。

1.3.3 Java语言创建对象

<类名> <对象名> = new <类名>([参数列表]);
注意:参数列表的内容,和定义该类的构造器有关。

举例:
Dog myDog; // 声明一个对象
myDog = new Dog(“花花”, 3); // 实例化
也可以在声明的同时进行初始化:
Dog myDog = new Dog(“花花”, 3);

举例:
Student xiaoming= new Student();
访问对象属性:
xiaoming.age;
调用对象方法:
xiaoming.study();

小贴士: eclipse快捷键: Ctrl + shift +f :自动补齐代码 Syso +alt + / :输出语句 Main / :自动生存入口方法 Ctrl + / :注释 Ctrl + d::删除 Ctrl + z :撤销 Ctrl +y :前一步 Alt shift s : 自动生存代码 Alt /:代码补全