Java程序设计系列讲座-3_第1页
Java程序设计系列讲座-3_第2页
Java程序设计系列讲座-3_第3页
Java程序设计系列讲座-3_第4页
Java程序设计系列讲座-3_第5页
已阅读5页,还剩56页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Java程序设计系列讲座程序设计系列讲座3OOP之继承性与多态性之继承性与多态性黄绍辉厦门大学计算机科学系E-mail: 来点轻松的话题:来点轻松的话题:Java命名规范命名规范包的命名规范包的命名规范包的名称一般全部采用小写包名的前缀一般是域名单词序列的逆序实例com.sun.engcom.apple.quicktimeedu.cmu.cs.bovik.cheese文件的命名规范文件的命名规范 必须与该文件中public类的类名同名 后缀必须是 .java类类/ /接口的命名规范接口的命名规范 类名一般是名词/名词词组:每个单词的首字母大写,其它字母小写 类名应当尽量简单,而且其含义能够尽量

2、准确地刻画该类的含义 一般采用全称尽量少用缩写词 (除非该缩写词被广泛使用) 实例 Clock Time ImageSprite方法的命名规范方法的命名规范 方法名一般是 动词/动词性词组 首字母小写 中间单词的首字母大写,其它字母小写 尽量应用简单的、常用的单词 实例 run( ); getBackground( ); getTime( );变量的命名规范变量的命名规范 变量名的首字母小写 中间单词的首字母大写,其它字母小写 变量名的首字母尽量不要用字符: _ 或 $ 变量名应当简短、有含义、且便于记忆 变量名常常由表示其所扮演的角色与数据类型组成 实例 int i; char c; dou

3、ble widthBox; Point startingPoint, centerPoint; Name loginName;常量的命名规范常量的命名规范 常量名一般全大写,单词之间用下划线分隔 (“_”) 实例: static final int MIN_WIDTH = 4; static final int MAX_WIDTH = 999;编辑方法编辑方法 尽量不要用TAB排版 行数/每行的字符数 缩排方式(Indentation) 空白符/行 友情提示:通常Java的开发环境都会提供源代码的格式化/重排功能,如果使用记事本编辑源代码,建议去下载一个叫astyle的源代码重排工具(DOS命

4、令行工具)。UltraEdit有捆绑这个工具,并提供了GUI界面的调用方式。文件组织文件组织 源程序文件一般采用如下的组织顺序: 最开始一般是注释 package 和 import 语句 类和接口的定义OOP-Part II 继承性继承性类的继承和实现类的继承和实现 一个类可以被继承,继承有什么好处呢? 当一个类被继承的时候,它所有说明为protected和public的成员(变量和函数)都可以传递到它的下一代,这就是好处。 例如图形界面的程序,一般都需要继承JFrame,因为JFrame这个类帮你做了很多事情:绘制一个界面,做一个标题栏,可以缩放要是你自己从头开始做一个类似功能的类,那难度可

5、就太可怕了 但是如果你继承JFrame的话,那么JFrame可以把它拥有的超过150个精心设计功能强大的函数转让给你使用!多好的JFrame啊直接继承直接继承JFrameJFrame类,界面就出来了类,界面就出来了 一个类可以被继承,例如这个MyGUI类:import javax.swing.*;public class MyGUI extends JFrame public static void main(String args) MyGUI frame = new MyGUI(); frame.setTitle(早上好!); frame.setSize(500, 400); frame.

6、setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 注意这个MyGUI类,其实除了继承,啥都没干,但是人家就是有界面超类和子类超类和子类 当一个类C1是从C2继承而来的,C1叫做子类(subclass),而C2叫做超类(superclass) 子类在OOP里还有一种叫法child class,或者扩展类(extended class),或者派生类(derived class) 超类也叫双亲类、父类(parent class),或者基类(base class) 子类通常具有比父类更强的功能,因为它不但能够

7、继承父类的成员,还可以添加属于自己的成员继承性继承性 创建子类格式:class SubClass extends SuperClass 这里SubClass就可以继承所有SuperClass的public和protected的成员,当然,如果SubClass有同名的成员,那么SuperClass的将被屏蔽。例如:class A public int a; protected int b; class B extends A int a; /此a将屏蔽父类的a void f() b+; /这里的b实际上是从A继承来的 又一个继承的例子又一个继承的例子class A protected int x

8、; public void f() x-; class B extends A B() x = 100; /这里直接使用的x,其实来自父类A f(); /f函数其实也是来自A,但现在可以直接使用 一个忠告一个忠告 由于无参的构造函数会被子类自动调用,因此如果一个类将来有可能被继承,一定要提供一个无参的构造函数。例如下面的代码会有编译错误: public class Apple extends Fruit class Fruit public Fruit(String name) System.out.println(Fruit的构造函数); super & thissuper &

9、; this Java中通过super来实现对父类父类成员的访问,super用来引用当前对象的父类。super 的使用有三种情况: 1)访问父类被隐藏的成员变量,如:super.variable; 2)调用父类中被重写的方法,如:super.Method(paramlist); 3)调用父类的构造函数,如:super(paramlist); this用于调用同一个类同一个类的成员变量或者成员方法,用法和super类似,其格式为: this.variable; this.Method(paramlist);thisthis的例子的例子class Point private int x,y; pu

10、blic void setX(int xx) this.x=xx; public int getX() return this.x; public void setY(int y) this.y = y; public int getY() return this.y; 注意只有斜体部分的this才是一定要使用this的场合,其它情况下并不需要this。supersuper和和thisthis的例子的例子class A protected int x; public void f() x-; class B extends A int x; void f() this.x+; /这里用的是自己

11、的x,也可以直接写x+ super.x = 100; /这里用的是父类继承来的x super.f(); /f函数其实也是来自父类 总结一下继承性总结一下继承性 public:包内及包外的任何类均可以继承或访问; protected:包内的任何类,及包外的那些继承了此类的子类才能访问; default:包内的任何类都可以访问它,而包外的任何类都不能访问它(包括包外继承了此类的子类) ; private:不能被继承,只能在类内部使用。 继承性的完整例子继承性的完整例子题目题目 我们想做一个类Circle表示平面直角坐标系上的一个圆(解析几何还记得吧.)。 然后我们想做一个求面积的成员函数。 我们还

12、要假定所有的Circle的成员变量都是private的,所有的成员函数都是public的,下面开始动手设计这个类。操作步骤操作步骤 1 1 先搭一个空架子总是没有问题的:class Circle操作步骤操作步骤 2 2 设计一下成员变量,这里三个足够了:class Circle private double r; /r是半径 private double x,y; /(x,y)是圆心坐标操作步骤操作步骤 3 3 然后是构造函数,这里先搞两个:class Circle private double r; private double x,y; public Circle() x=0; y=0;

13、r=1; public Circle(double x, double y, double r) this.x=x; this.y=y; this.r=r; /亲,不小心又用到了this,还记得this干吗的不? 操作步骤操作步骤 4 4 然后是面积函数:class Circle private double r; private double x,y; public Circle() x=0; y=0; r=1; public Circle(double x, double y, double r) this.x=x; this.y=y; this.r=r; public double ge

14、tArea() return (Math.PI*r*r); EclipseEclipse测试程序测试程序 综合一下以上的所有步骤: 先建一个工程,名字随意,再建一个类,名字叫Circle,然后把Circle的代码贴上; 再建一个类,名字随意,例如叫Test,勾上自动生成main函数的选项; 现在你的工程里应该有两个java源文件,两个类,其中一个是用来测试的类,所以它有main函数,Circle类由于没有main函数,所有它是不能运行的。因此启动运行的主类是Test。TestTest类的写法类的写法public class Testpublic static void main(String

15、args) Circle c1 = new Circle();System.out.println(c1.getArea();Circle c2 = new Circle(3.0,4.0,5.0);System.out.println(c2.getArea();CircleCircle的改进的改进 Circle类显然不完善,例如你在Test类里,如果想知道c1的x,y,r三个成员分别是多少,可能吗?如果你想在Test类里,随时修改c1的半径,可能吗? 答案显然不行,所以,Circle其实还有很多的成员函数需要添加。 这里就不演示了,自己动手试试。研究一下对象的引用研究一下对象的引用 一个类的成

16、员函数(static除外),是不是一定要new才能被使用呢?例如GUI编程中经常有这种语句:Container container = getContentPane(); container.add(new Button(button1); 这个container好像就没有new对吧?怎么就可以抓来用呢?难道随便get一下也能用? 其实这个container已经被new过了,只是你没有看见而已。get一下相当于做对象的引用。这么说好像很复杂,看一个例子:对象的引用对象的引用 I I class A public int x; public class Testpublic static voi

17、d main(String args) A a = new A(); a.x = 1; System.out.println(a.x=+a.x); A b = a; /注意这里注意这里b不是不是new出来的出来的 b.x = 10; System.out.println(b.x=+b.x); System.out.println(a.x=+a.x); a.x = 100; System.out.println(a.x=+a.x); System.out.println(b.x=+b.x); 这个例子的输出是:a.x=1b.x=10a.x=10a.x=100b.x=100对象的引用对象的引用 I

18、I II 总结一下,如果一个对象不是new出来的(例子中的b),而是直接用一个已经new出来的对象(例子中的a)给它赋值,那么这个对象b就叫做a的引用。 引用的对象之所以可以直接使用,不需要new,其实是因为它所指向的对象和赋值给它所指向的对象和赋值给它的对象是同一个它的对象是同一个!也就是它只是给原来的对象起了一个别名而已。对象的引用对象的引用 IIIIII 总结一下,类似下面这样总结一下,类似下面这样b=a的操作叫做对的操作叫做对象引用:象引用: A a = new A(); A b=a; 对象的引用乍看上去有点类似对象整体赋值,因为在某些高级语言中,确实会把a整体复制一遍给b,于是a和b

19、仅仅内容相同而已,但是属于不同对象;但是Java对这句话的理解却是:b仅仅是a的别名,a和b其实表示同一个对象。所以别把语言搞混了。OOP-Part III 多态性多态性多态性多态性 静态多态性 体现在方法的重载 在编译阶段,具体调用哪个被重载的方法,编译器会根据参数的不同来静态确定调用相应的方法。 动态多态性 由于子类继承了父类所有的属性(私有的除外),所以子类对象可以作为父类对象使用。程序中凡是使用父类对象的地方,都可以用子类对象来代替。一个对象可以通过引用子类的实例来调用子类的方法。 重写方法的调用原则(匹配原则):对子类的一个实例,如果子类重写了父类的方法,则运行时系统调用子类的方法;

20、否则调用父类的方法。静态多态性:函数重载静态多态性:函数重载class A A() A(int i) i+; void fun(int i) i+; void fun(double f) f+; void fun(int i, int j) i+; j+; 上例中函数A和fun都算重载。 重载的特征:函数名相同重载的特征:函数名相同 重载的两个要素:重载的两个要素: 参数类型不同参数类型不同 参数个数不同参数个数不同 重载与返回值无关重载与返回值无关动态多态性动态多态性当继承发生的时候,动态多态性就来了当继承发生的时候,动态多态性就来了有个例子有个例子class A public void f

21、un() System.out.println(“A”); class B extends A public void fun() System.out.println(“B”); class C extends B public void fun() System.out.println(“C”); class Test public static void main(String args) A a; B b = new B(); C c = new C(); a=b; a.fun(); / 此处将输出Ba=c; a.fun(); / 此处将输出C 解释一下解释一下 Java 的动态多态性

22、这种机制遵循一个原则:当超类(父类)对象的引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法; 当然,这个被调用的方法必须是必须是在超类中定义过的,也就是说被子类覆盖的方法。你可能会问,如果这个方法没有被覆盖呢?Good question还有个例子还有个例子class A public void fun() System.out.println(“A”); class B extends A public void funB() System.out.println(“B”); class C extends B public void funC() Syste

23、m.out.println(“C”); class Test public static void main(String args) A a; B b = new B(); C c = new C(); a=b; a.fun(); / 此处将输出Aa=c; a.fun(); / 此处将输出A 总结一下总结一下 Java在函数调用的时候,是按照这个顺序查找函数的:1. 先看看自己有没有这个函数,如有则调用;2. 向上一级,看看有没有这个函数,一直上溯到找到函数为止。 Java的子类可以直接转化直接转化为父类( class B extends A ) 如:B b = new B(); A a =

24、 b; /注意这里a是引用 Java的父类必须强制转化强制转化为子类( class B extends A ) 如:A a = new A(); B b = (B)a; /这个操作没意义 或:B b = new B(); A a = b; B bb = (B)a;/这个倒可以,但是绕了一圈,还不如直接用:bb = b,效果一样抽象类与接口抽象类与接口 I I 是不是所有的类都可以new出来用?答案是:NO!因为抽象类就不可以。它只能被继承。 接口是一种特殊的抽象类,它也不能被new出来,而只能被实现(implements)。 抽象类的定义是在class前面加上一个abstract,而接口的定义

25、是把class关键字换成了interface。抽象类与接口抽象类与接口 II II 例如:class A /A是类 . abstract class B /B是抽象类 . interface C /C是接口,一种特殊的抽象类 . 为什么需要抽象类?为什么需要抽象类?I I 在面向对象的概念中,所有的对象都是通过类来描述的,但是反过来却不是这样:并不是所有的类都是用来描述对象的并不是所有的类都是用来描述对象的,如果一个类中没有包含足够的信息来描述一个具体的对象,这样的类就是抽象类。 抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的

26、抽象。 为什么需要抽象类?为什么需要抽象类?II II 比如:圆、三角形、矩形这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。 正是因为抽象的概念在问题领域没有对应的具体概念,所以用以表征抽象概念的抽象类是不能够实例化的。为什么需要抽象类?为什么需要抽象类?IIIIII 如果我们要设计一个Shape的类,用来表示几何形状;内含一个函数getArea,表示这个形状的面积可是这个面积目前是无法求的,因为我们的信息太少,所以,这个Shape只能设计成抽象类。 在Shape基础上,我们可以继承出一个类Rect,用来表示矩形;也设计

27、一个类Circle,用来表示圆形;显然,这两个类的getArea函数体是可以实现的。为什么需要抽象类?为什么需要抽象类?IVIV abstract class和interface在Java语言中都可以用来设计抽象类。 abstarct class在Java语言中体现了一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在“is a”关系,即父类和派生类在概念本质上应该是相同的。 例如上一个例子,Rect和Circle都是一种形状,因此用Shape做父类是很自然的。此时Shape设计成abstract class在概念上也比较好接受。为什么需要抽象类?为什么需要抽象类?V V interf

28、ace表示的是“like a”或者“has a”关系。我们用一个例子来表明,尽管都可以表示抽象类,但是abstract class并不是万能的。 例如我们设计一个类HaoJiao,用来描述动物的嚎叫。显然各种动物嚎法不同,所以这个类没法具体实现,因此只能设计成抽象类。可是,HaoJiao好继承吗?难道有更高级的HaoJiao? 如果我们还有一个类Animal,显然它应该会有HaoJiao的属性,但是Animal不能继承自HaoJiao(否则在概念上实在不好理解)。于是我们只能将HaoJiao设计成interface,然后类Animal可以实现实现(implements)这个接口。抽象类与接口抽

29、象类与接口 IIIIII 抽象类有一个特殊的规定,它里面的抽象函数在继承的类中一定要被重写!(为什么呢?如果你接受不了这个事实,参见刚翻过的5页PPT) 接口也有一个特殊的规定,它里面的抽象函数在实现的类中一定要被重写!(不过很不幸,接口里所有的函数都是抽象的,所以它是特殊抽象类) 所以总结起来就是一点,抽象函数在设计的时候,抽象函数在设计的时候,自己是不用写函数体的(其实是想写也写不了,自己是不用写函数体的(其实是想写也写不了,呵呵);但是一旦被继承呵呵);但是一旦被继承extends或者实现或者实现implements,函数体就一定要被具体实现。,函数体就一定要被具体实现。抽象类和继承的例

30、子抽象类和继承的例子abstract class A abstract public void f(); /注意这里没有函数体class B extends A public void f() /注意这里已经实现了f函数,尽管只是空函数class C extends A double x; public void f() x=100; /注意这里已经实现了f函数 public void ff() x+; /这个是C自己的函数接口和实现的例子接口和实现的例子interface A abstract public void f(); /注意这里没有函数体class B implements A p

31、ublic void f() /注意这里已经实现了f函数,尽管只是空函数class C implements A double x; public void f() x=100; /注意这里已经实现了f函数 public void ff() x+; /这个是C自己的函数接口总结接口总结 接口是一种特殊的抽象类,所以它仍然具有类的特点。 Java在继承机制上,只支持单一继承(也就是任何类的父类只有一个)。假设你现在想同时把A类和B类的遗产继承过来,就只能借助于接口了。因为Java允许你实现多个接口,用逗号隔开就可以,当然前提是A和B你要先改成接口才行。 顺便说一句,当你随手写一个class A,而没有继承任何类的时候,其实这个A并不是孤零零的,因为Java会认为A继承了java.lang.Object。内部类内部类 I I 为什么需要内部类? Java中的内部类和接口加在一起,可以有效解决常被C+程序员抱怨Java中存在的一个问题没有多继承。实际上,C+的多继承设计起来很复杂,而Java通过内部类加上接口,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论