版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Java程序设计系列讲座2OOP之封装性黄绍辉厦门大学计算机科学系E-mail: 面向对象程序设计基本思想对象的基本概念对象是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。一个对象由一组属性和对这组属性进行操作的一组服务组成。对象是问题域或实现域中某些事物的一个抽象,它反映该事物在系统中需要保存的信息和发挥的作用;它是一组属性和有权对这些属性进行操作的一组服务的封装体。客观世界是由对象和对象之间的联系组成。类的基本概念类是具有相同属性和服务的一组对象的集合。分类的原则是抽象。在面向对象的编程语言中,类是一个独立的程序单位,它应该有一个类名并包括属性说明和服务说明两个主要部分。类
2、与对象的关系就如模具和铸件的关系,类的实例化结果就是对象,而对一类对象的抽象就是类。关于OOPObject Oriented Programming 对象是基本编程单位。与此对应,Java使用类(class)表示对象,一个class就是一个类;对象由一组属性和一组服务两部分组成(两部分不必都存在)。与此对应,Java使用一组成员变量(member variable)表示属性,一组成员函数(member method)表示服务。OOP的例子例如我们要表示一个遥控器对象,它起码有两个属性:外壳,按钮。它起码有两个功能:换台,调音量。使用Java来设计这个对象,它看起来就是这个样子:class 遥控
3、器 外壳成员 按钮成员 换台函数() 调音量函数()OOP的基本特征封装性把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节。继承性从一个已有的类来构造新类,除了保留原有的类的特性,还增加了一些新特性。已有的类称为父类superclass,新类称为子类subclass。多态性在父类中定义的属性或服务被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为。 OOP-Part I 封装性从C语言开始出发任务:在程序中实现对时间的一些操作思路:时间是一个整体,包括时/分/秒,为了在程序中表示一个具体的时间,这三个部份缺一不可。最自然的,可以采用三个整型变量来存储这三个部份,例
4、如:int hour;int minute;int second;C程序示例void main()int hour,minute,second; hour=12; minute=12; second=12; printf(“Time is %d:%d:%d”,hour,minute,second);如果有很多个时间void main()int hour1,minute1,second1;int hour2,minute2,second2;int hour3,minute3,second3;printf(“Time1 is %d:%d:%d”,hour1,minute1,second1);pri
5、ntf(“Time2 is %d:%d:%d”,hour2,minute2,second2);printf(“Time3 is %d:%d:%d”,hour3,minute3,second3);如果用数组void main()int hour100,minute100,second100;for(int i=0;ihour +;使用示例:struct MyTime t;t = AddOneHour(t);使用示例:struct MyTime t;AddOneHour(&t);关于上面两个函数的探讨前面说过,struct MyTime已经可以看成是对象了,从上面的两个函数可以看出,为了修改对象的
6、属性,比较好的作法,是(通过指针)直接修改对象本身的属性,代码简单,效率也高。但是C毕竟是面向过程的语言,实现 “对象的加工”或者叫“对象的服务”,需要借助struct MyTime之外的函数AddOneHour完成。OOP语言的第一个方便之处,就是把属性和服务整合到同一个对象中,这给编程带来了极大的方便,例如:Java版本的AddOneHourclass MyTimeint hour;int minute;int second;void AddOneHour() hour+; 使用示例:MyTime t=new MyTime();t.AddOneHour();把属性和服务整合到同一个对象内部
7、的最大好处,是你不再需要将一个结构作为一个参数传入到外部的处理函数,也不需要考虑将处理后的结果从函数传出,甚至贴代码的时候,都不用担心会少贴一个函数看出封装的好处了吗? C的结构可以存储数据,但是不能包含函数,因此必须在其它的地方定义函数。这个做法可能导致以下后果:调用不方便,参数要传入传出毕竟是比较麻烦的可能和别人写的函数产生冲突(例如重名)代码的重用和修改不方便Java可以将数据和处理函数一起封装,因此数据以及对数据的加工都可以在同一个对象当中完成。总结一下封装性OOP中,对象就是对一组变量和相关方法的封装,其中变量表明了对象的状态,方法表明了对象具有的行为。简单一点说,封装性指的是:属性
8、和函数都放在同一个对象的内部。对Java而言就是:一个class可以内部可以有多个成员变量和多个成员函数;成员函数可以直接访问成员变量,并对其进行修改。通过对象的封装,实现了模块化和信息隐藏。跑步进入OOP有个例子从简单对象入手对象不是很深奥的东西,一个对象在Java里面就是一个class而已。例如随便写一个对象:class Point /首字母大写是Java建议的对象命名规则 int x,y;这个Point对象可以用来表示平面上的一个点。注意Java并不要求对象一定要有成员函数,所以这个对象已经很完整,只是还不够好用而已,接下来我们会逐步完善它。对象的用法要使用一个已有的对象不是太难,但是你
9、要做足以下的两件事情:使用对象的名字声明一个变量创建对象的一个实例用上面的Point做例子,就是这样:使用对象的名字声明一个变量 Point p;创建对象的一个实例 p = new Point();接下来这个p就拥有了Point的全部资源,例如它有两个成员变量,叫x,y,而且还是整型的。对象的用法对象的声明和创建可以合成一步:Point p = new Point();当然也可以隔了很多步:Point p;/* 中间有很多很多很多行,但是和p无关 */p = new Point();只有一个准则:对象在创建之前是不能使用的,所以new很重要。对象与实例前面说到,对象必须创建才能使用,所以你必须
10、这样创建p:Point p = new Point();这里引入几个术语: Point 是类名,也是对象名,或者干脆叫对象 p 是对象的实例,也就是Point的实例你可以理解对象是一个图章,它每盖章一次(new一次)生成一个p,p就是一个实例。一个完整例子:Test.javaclass Point int x,y;public class Test public static void main(String args) Point p = new Point(); System.out.println(“p.x=”+p.x+“ p.y=”+p.y); p.x = 1; p.y = 2; Sy
11、stem.out.println(“p.x=”+p.x+“ p.y=”+p.y); 插播一下:数组使用对象我们刚刚学会两招:招式一:对象可以同时拥有属性和函数;招式二:对象要new以后才能使用下面我们来用这两招对付Java的一个常用对象:数组。和C语言不同,Java把数组设计成了对象,所以根据我们的招式二,Java的数组必须先new才能使用。如果你能够意识到这一点,那么恭喜你,OOP入门成功数组入门11 声明一个数组dataType arrayRefVar;或 dataType arrayRefVar; 例如:double myList;2 创建一个数组arrayRefVar = new da
12、taTypearraySize;如:myList = new double10;数组入门2声明并创建一个数组dataType arrayRefVar = new dataTypearraySize;或 dataType arrayRefVar = new dataTypearraySize;例如:double myList = new double10;数组入门3数组在创建之后,Java会为这个数组自动分配空间。(注意声明数组的时候并没有分配数组元素空间,因为那时候不知道数组多大)数组入门4任何一个数组,都可以通过属性length得到数组的长度。如: myList.length数组创建的时候会
13、自动赋零值,对于数值型的,就是0或者0.0或者0,对于布尔型的,就是false任何一个数组,其元素的最小下标是0,最大下标是length-1数组下标越界会引发异常数组入门5数组元素的引用使用 ,以下两个方法可以打印出数组myList的每一个元素值:for (int i = 0; i myList.length; i+) System.out.print( +myListi);或者(JDK1.5以上版本才支持的)for (int val : myList) System.out.print( +val);数组入门6数组在创建的时候可以顺便初始化,如:double myList = 1.9, 2.
14、9, 3.4, 3.5;它相当于:double myList = new double4;myList0 = 1.9;myList1 = 2.9;myList2 = 3.4;myList3 = 3.5;数组例程1/3 用100以内随机数初始化数组for (int i = 0; i myList.length; i+) myListi = Math.random() * 100;数组例程2/3数组求和double total = 0;for (int i = 0; i myList.length; i+) total += myListi;数组例程3/3求数组中的最大值double max =
15、myList0;for (int i = 1; i max) max = myListi;数组作为函数参数1数组作为参数,Java采用的是引用传递方式,基本数据类型(int,char等)作为参数,采用值传递方式。简单一点说,引用传递方式,实际参数和形式参数,操作的其实是同一个对象;值传递方式,实际参数和形式参数,操作的是不同对象,仅仅是这两个对象的值相等而已。数组作为函数参数2public class Test public static void main(String args) int x = 1; / x represents an int value int y = new int1
16、0; / y represents an array of int values m(x, y); / Invoke m with arguments x and y System.out.println(x is + x); / x值不变,还是1 System.out.println(y0 is + y0); / y0值已改变,本来是0的 public static void m(int number, int numbers) number = 1001; / Assign a new value to number numbers0 = 5555; / Assign a new valu
17、e to numbers0 数组作为函数参数3 1 public class TestPassArray 2 /* Main method */ 3 public static void main(String args) 4 int a = 1, 2; 5 6 / Swap elements using the swap method 7 System.out.println(Before invoking swap); 8 System.out.println(array is + a0 + , + a1 + ); 9 swap(a0, a1); /值传递,返回后不改变原值10 Syste
18、m.out.println(After invoking swap);11 System.out.println(array is + a0 + , + a1 + );1213 / Swap elements using the swapFirstTwoInArray method14 System.out.println(Before invoking swapFirstTwoInArray);15 System.out.println(array is + a0 + , + a1 + );16 swapFirstTwoInArray(a); /引用传递,返回后原值可能改变17 System
19、.out.println(After invoking swapFirstTwoInArray);18 System.out.println(array is + a0 + , + a1 + );19 数组作为函数参数420 /值传递,返回后不改变原值21 /* Swap two variables */22 public static void swap(int n1, int n2) 23 int temp = n1;24 n1 = n2;25 n2 = temp;26 27 /引用传递,返回后原值可能改变28 /* Swap the first two elements in the a
20、rray */29 public static void swapFirstTwoInArray(int array) 30 int temp = array0;31 array0 = array1;32 array1 = temp;33 34 多维数组1二维数组的定义dataType arrayRefVar;或 dataType arrayRefVar; 例如:int matrix;或 int matrix;注意,这里仅仅说明matrix是一个二维数组,但是这个数组的大小还未知,所以还不能存储元素。多维数组2二维数组有行和列的概念,如:多维数组3二维数组可以在声明的时候赋初值,也可以在new
21、之后再一个一个慢慢赋值。其实二维数组行和行之间是相互独立的,每一行都相当于一个一维数组。由于二维数组的每一行是一个一维数组,所以这些一维数组的大小不必相等,如:此时:triangleArray.length = 5, /因为数组有5行triangleArray0.length = 5, triangleArray1.length = 4, triangleArray2.length = 3, triangleArray3.length = 2, triangleArray4.length = 1.多维数组4二维数组例程1随机数填充for (int row = 0; row matrix.len
22、gth; row+) for (int column = 0; column matrixrow.length; column+) matrixrowcolumn = (int)(Math.random() * 100); 这里matrix是二维数组。过一遍二维数组必须用两层的循环,一般用i循环行,j循环列;如果英文好一点,可以用row循环行,column或者col循环列。二维数组例程2打印数组元素for (int row = 0; row matrix.length; row+) for (int column = 0; column matrixrow.length; column+) S
23、ystem.out.print(matrixrowcolumn + ); System.out.println();二维数组例程3数组求和int total = 0;for (int row = 0; row matrix.length; row+) for (int column = 0; column matrixrow.length; column+) total += matrixrowcolumn; 杨辉三角的例子public class Yanghui public static void main(String args) int a=new int1010; for(int i
24、=0;i10;i+) for(int j=0;j=i;j+) if(j=0|i=j) aij=1; if (i9) ai+1j+1=aij+aij+1; System.out.print(aij+ ); System.out.println(); 研究一下构造函数创建对象前面说到,对象必须创建才能使用,那么创建对象Point是不是只有一种方法呢?默认的显然是只有一种,所以你只能这样创建p:Point p1 = new Point();但是实际生活里,我们必须有多种途径来创建对象,这样用起来才方便。例如你可能希望这样创建: Point p2 = new Point(1,2); 然后期待着p2的x
25、和y成员分别是1和2,如何做到这一点呢?什么是构造函数可不可以换一种方式创建Point?当然可以,不过你要自己加构造函数,例如:class Point int x,y; Point(int xx, int yy) x=xx;y=yy;注意上面那个函数,它有两大神奇之处:没有定义返回值,连void都没有名字和类的名字完全一样这种写法奇怪的函数就是传说中的:构造函数默认构造函数现在你终于可以这样创建一个p了: Point p = new Point(1,2);不过你现在反而不能这样创建一个p了:Point p = new Point(); why?关于构造函数 I构造函数和类的名字完全一样,并且没
26、有返回值,它的作用是提供类的创建方式,所以,根据类必须先创建再使用的原则,构造函数是每一个类一定要具备的东西。或许你注意到第一个版本的Point没有构造函数,是的,不过Java是这样聪明的一个语言,所以它会帮你补充一个不带参数,没有函数体的构造函数,例如Point类,它偷偷加的代码是:class Point int x,y; Point() /这一行尽管你没看见,但是它确实存在关于构造函数 IIJava自动提供构造函数仅仅当你自己没有提供构造函数的时候才这么干,如果你提供了哪怕只有一个的构造函数,它决不自作多情帮你加一个。所以第二个版本的Point最好改成下面:class Point int
27、x,y; Point() /由于Java罢工,这个函数只好自己加 Point(int xx, int yy) x=xx;y=yy;关于成员变量对内篇每一个类都可以有自己的成员变量,例如Point类的x和y;对于Point类的内部而言,x,y相当于全局变量;如果脱开Point类,那么就要看x,y是怎么声明的了。class Point Point() x=10; y=10; Point(int xx, int yy) x=xx;y=yy; int x,y; x,y的作用范围从这里开始x,y的作用范围到这里结束关于成员变量对外篇成员变量有四种修饰,它们决定了外部访问成员变量的权限:private,d
28、efault,protected、public对于private,实际上是不允许外部访问的,所以如果你的Point这样定义:class Point private int x,y;然后有 Point p = new Point();那么这两个语句是错的:p.x=10; p.y=10;关于成员变量对外篇如果这个时候你想从外面修改x,y的值怎么办?答案是:没法改!除非Point类另外提供函数给你用,例如:class Point private int x,y; public int getX() return x; /这就是传说中的getter public void setX(int xx) x
29、=xx; /传说中的setter上帝保佑,现在你终于可以从外面改x的值了:Point p = new Point();p.setX(100); System.out.print(p.getX();关于成员函数 I成员函数的访问权限和成员变量完全一样,所以这里不重复了。成员函数的调用,也要通过对象的实例才能够调用(当然静态函数除外,后面再讲),不会忘记什么叫对象的实例了吧?Oh, my God!还是加一个函数试试,例如我们给Point加一个成员函数:public double test(double s) return x*y*s; 关于成员函数 II 现在我们来调这个函数(这里是在外部调,如果
30、在类的内部调,那就直接调用就好了)Point p = new Point(3,4);System.out.print(p.test(5.0); /通过p调用test函数还是不太放心,演示一下对象内部怎么调test:class Point private int x,y; public double f() return test(5.0); public double test(double s) return x*y*s; 关于成员函数 III 总结一下,一个类的成员函数:对于类的内部而言,是直接抓过来随便爱怎么调用都行(多大公无私啊),不需要借助任何东西;对于类的外部而言,如果是priva
31、te的成员函数,那显然是不能用的;如果遇到public的,那运气还不错,可以通过创建一个类的实例(也就是new一下),来间接调用这个成员函数。成员变量的结论与此类似。顺便说一下,在一个类的外部,每次new一个实例的时候,相当于调用一次构造函数;至于调用的是哪一个构造函数,那要看你给的参数了。关于静态方法和静态成员 I如果一个class有一个static的成员,那使用的时候要小心一点。给一个例子:class A public int x; public static int y; public static void f() System.out.print(x+y); 还记得怎么调用f,怎么使
32、用x,y么?很简单:A a = new A(); /看到这句不要晕掉,好多a.a.x = 10; a.y = 10; a.f(); /调用函数f,不要参数关于静态方法和静态成员 II下面来一段复杂的测试代码,测试A这个类:class Test public static void main(String args) A a = new A(); a.x = 10; a.y = 10; A b = new A(); b.x = 100; b.y = 100; System.out.print(a.x=+a.x+a.y=+a.y+b.x=+b.x+b.y=+b.y); 运行上面程序,你会发现一个奇
33、怪的现象:a.x不等于b.x,可是a.y居然等于b.y前一半比较好理解,因为a和b本来就是不同的实例,虽然它们是一个模子造出来的;可是,那y怎么回事?关于静态方法和静态成员 III其实,静态成员是如此特殊的一个东西,因为它是所有实例共享的!也就是无论你new多少个实例出来,静态成员自始至终就是一个而已。而且,就算是你没有new过实例,它就已经存在了,神奇吧?所以,java鼓励你这样直接使用静态成员:A.y = 100; A.f(); /注意这里没有实例噢,A亲自上阵了所以,静态成员变量在java里一般被用作共享的常数,例如Math.PI,所以你可以常常看到final和static一起混的情形;
34、静态成员函数一般被用作全局函数,供任意类调用,例如Math.sin()再次啰唆一下类成员的访问控制类成员总共有四种访问模式:private,protected,public以及default,它们的访问控制如下:确定访问控制权限的原则基于安全性的考虑,在能满足设计要求的前提下,访问权限越严格越好一个例子class Root private int a; protected float b; public double c; char d; void fun() a+; b+; c+; d+; /类的内部,成员变量相当于全局 /变量,在任何函数中均可直接用 假设有一个类的实例 Root r =
35、new Root();那么 r.a+就是错误的,因为这相当于在类的外部使用变量;但是 r.c+是正确的,因为c是public,支持外部访问。关于封装的进一步探讨 Java的封装属性有四个(按开放程度排序): private,default,protected以及public。一般来说,封装越严格越好,因此尽量不要将成员变量设置为public。当把成员变量设置为private时,为了能够提供外部类对这些成员变量的存取,一般要设置一堆的public的get方法和set方法。例如对hour成员:public int getHour() return hour; public void setHour
36、(int h) hour = h; 方法重载方法重载是指多个方法享有相同的名字,但是这些方法的参数必须不同,或者是参数的个数不同,或者是参数类型不同。返回类型不能用来区分重载的方法。再次啰唆一下构造方法 构造方法是一个特殊的方法。Java 中的每个类都有构造方法,用来初始化该类的一个对象。 构造方法具有和类名相同的名称,而且不返回任何数据类型。 重载经常用于构造方法。 构造方法只能由new运算符调用。关于构造方法以及new 要生成一个对象的实例,必须使用new运算符。每次new的时候,对象的构造方法会被自动调用。构造的方法可能有很多个,new的时候调用哪一个取决于new的时候带的参数。例如:M
37、yTime t1=new MyTime(); /调用无参数的构造方法MyTime t2=new MyTime(hour, second, minute);/调用使用三个参数的构造方法,注意三个参数的类型/要和构造方法声明的参数类型保持一致一个练习写一个类Person表示一个人,用name和age表示其姓名和年龄,并提供以下三个构造函数: Person(); /默认名字为 noname,年龄为0 Person(String name); /年龄默认为0 Person(String name, int age);在main函数中使用以上三种构造方式创建3个Person对象,然后输出。异常异常和异常
38、类型异常是程序运行时发生的错误。当异常发生时,常常导致程序崩溃,从而丢失尚未保存的数据。用户输入非法是异常的主要来源,例如:异常是可以捕捉的Java允许你自己去捕捉异常,从而避免程序崩溃。例如上例可以修改为:异常处理(I)异常分类:受检异常(编程时一定要检测的异常)非受检异常异常的层次:异常处理(II)异常产生:运行时(被动)产生主动抛出throw异常处理捕获try.catch( ExceptionName1 e ).catch( ExceptionName2 e ).finally.异常处理(III) try 捕获例外的第一步是用try选定捕获例外的范围,由try所限定的代码块中的语句在执行过程中可能会生成例外对象并抛弃。 catch 每个
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 编辑部第二学期工作计划
- 财务会计工作总结与计划范文
- 护士入职面试自我介绍新入职护士培训计划
- 服务中心个人某年度工作计划
- 2024-2024年第二学期小学安全工作计划范文
- 工作计划结尾例文
- 学校远程教育工作计划范文
- 公司班组建设工作计划
- 2024六年级上学期班务工作计划
- 农村法律顾问个人工作计划
- 《公路桥梁施工监控技术规程》(JTGT3650-01-2022)
- 高空蜘蛛人施工专项施工方案
- 生物甲烷行业竞争分析及发展前景预测报告
- 体育赛事后勤服务行业发展趋势及前景展望分析报告
- 新华锦2023年投资性房地产评估报告
- 大连市金普新区2022-2023学年七年级上学期期末数学试题【带答案】
- 2024年美国户外露营装备市场现状及上下游分析报告
- 2024年大学试题(财经商贸)-博弈论笔试考试历年高频考点试题摘选含答案
- 《液压与气压传动》课程期末考试题库及答案(A卷)
- 软件项目投标技术方案(技术方案)
- 集中空调微生物检测技术及质量控制
评论
0/150
提交评论