第5章类的继承性与多态性.ppt

上传人:本田雅阁 文档编号:2566922 上传时间:2019-04-09 格式:PPT 页数:44 大小:480.51KB
返回 下载 相关 举报
第5章类的继承性与多态性.ppt_第1页
第1页 / 共44页
第5章类的继承性与多态性.ppt_第2页
第2页 / 共44页
第5章类的继承性与多态性.ppt_第3页
第3页 / 共44页
第5章类的继承性与多态性.ppt_第4页
第4页 / 共44页
第5章类的继承性与多态性.ppt_第5页
第5页 / 共44页
点击查看更多>>
资源描述

《第5章类的继承性与多态性.ppt》由会员分享,可在线阅读,更多相关《第5章类的继承性与多态性.ppt(44页珍藏版)》请在三一文库上搜索。

1、第5章 类的继承性与多态性,5.1 类的继承 5.2 类的多态 习题,新类可从现有的类中产生,将保留现有类的状态属性和方法并可根据需要加以修改。新类还可添加新的状态属性和方法,这些新增功能允许以统一的风格处理不同类型的数据。这种现象就称为类的继承。,5.1 类的继承,当建立一个新类时,不必写出全部成员变量和成员方法。只要简单地声明这个类是从一个已定义的类继承下来的,就可以引用被继承类的全部成员。被继承的类称为父类或超类(superclass),这个新类称为子类。 Java提供了一个庞大的类库让开发人员继承和使用。通常要对子类进行扩展,即添加新的属性和方法。这使得子类要比父类大,但更具特殊性,代

2、表着一组更具体的对象。继承的意义就在于此。,5.1.1 父类和子类,在类的声明语句中加入extends关键字和指定的类名即可实现类的继承,例如: public class MyApplet extends java.applet.Applet public class MyApplication extends Frame public class MyApp1 extends Object public class MyApp2 那么,类的继承是从什么地方开始的?又是如何延续下来的呢?请看图5.1所示的模拟图。 图5.1反映了Java类的层次结构。最顶端的类是Object,它在java.la

3、ng中定义,是所有类的始祖。一个类可以有多个子类,也可以没有子类,但它必定有一个父类(Object除外)。,图 5.1,子类不能继承父类中的private成员,除此之外,其他所有的成员都可以通过继承变为子类的成员。另一方面,对继承的理解应该扩展到整个父类的分支,也就是说,子类继承的成员实际上是整个父系的所有成员。 因此,可以得出如下结论: 子类只能有一个父类。如果省略了extends,子类的父类是Object。子类继承了父类和祖先的成员,可以使用这些成员。在需要的时候,子类可以添加新的成员变量和方法,也可以隐藏父类的成员变量或覆盖父类的成员方法。,1. 成员变量的继承 例5.1 下面的3个程序

4、说明从点Point类扩展到线Line类和圆Circle类的方法,这是3个公共类,不能放在同一个文件中。它们都没有输出语句,即使补上相应的 main() 使之运行也看不到什么结果。 public class Point protected int x, y; Point(int a, int b) setPoint(a, b); public void setPoint(int a, int b) x=a; y=b; public int getX() return x;,5.1.2 成员变量的继承和隐藏,public int getY() return y; public class Line

5、 extends Point protected int x, y, endX, endY; Line(int x1, int y1, int x2, int y2) setLine(x1, y1, x2, y2); public void setLine(int x1, int y1, int x2, int y2) x=x1; y=y1; endX=x2; endY=y2; public int getX() return x ; public int getY() return y ; public int getEndX() return endX; public int getEnd

6、Y() return endY; public double length() return Math.sqrt(endX-x) * (endX-x) + (endY-y) * (endY-y);, public class Circle extends Point protected int radius; Circle(int a, int b, int r) super(a, b); setRadius(r); public void setRadius(int r) radius=r; public int getRadius() return radius; public doubl

7、e area() return 3.14159*radius*radius; 上例中,Point类具备一个点的特征。Line和Circle类具备线和圆的特征,但它们都是从Point继承下来的。下面分析一下这3个类各自都有哪些成员。,Point: x, y / 受保护的成员变量,代表点的坐标 Point / 点的构造方法 setPoint / 设定点的坐标值的方法 getX, getY / 返回坐标x和y的值的方法 Line: x, y, endX, endY / 子类受保护的成员变量,代表线的两个端点坐标 Line / 线的构造方法 setLine / 设定线的两个端点坐标值的方法 getX,

8、 getY / 返回起点坐标x和y的值的方法 getEndX, getEndY / 返回终点坐标endX和endY的值的方法 length / 返回线的长度的方法 x, y / 继承父类的受保护成员变量,但被子类隐藏 setPoint / 继承父类的方法 getX, getY / 继承父类的方法,但被子类覆盖,Circle: radius / 子类受保护的成员变量,代表圆的半径 Circle / 圆的构造方法 setRadius / 设定半径值的方法 getRadius / 返回半径值的方法 area / 返回圆面积的方法 x, y / 继承父类的受保护成员变量 setPoint / 继承父类

9、的方法 getX, getY / 继承父类的方法 从上面的分析可以看到,子类Circle继承了父类Point中的成员变量x和y,也继承了setPoint、getX和getY方法。添加了自己的成员变量radius,成员方法setRadius、getRadius和area。在构造方法Circle中,调用了父类的构造方法设定圆心坐标。,2. 成员变量的隐藏 所谓隐藏是指子类重新定义了父类中的同名变量,如子类Line重新定义了x为x1,y为y1,隐藏了父类Point中的两个成员变量x和y。子类执行自己的方法时,操作的是子类的变量,子类执行父类的方法时,操作的是父类的变量。在子类中要特别注意成员变量的命

10、名,防止无意中隐藏了父类的关键成员变量,这有可能给你的程序带来麻烦。 Line还覆盖了Point的两个方法getX和getY。关于方法覆盖,请看下面的内容。,通过继承子类可以继承父类中所有可以被子类访问的成员方法,但如果子类的方法与父类方法同名,则不能继承,此时称子类的方法覆盖了父类的那个方法,简称为方法覆盖。方法的覆盖(override),为子类提供了修改父类成员方法的能力。例如,子类可以修改层层继承下来的toString方法,让它输出一些更有用的信息。例5.2显示了在子类Circle中添加toString方法,用来返回圆半径和圆面积信息。,5.1.3 成员方法的覆盖,例5.2 对Objec

11、t的toString方法的覆盖示例,结果如图5.2所示。 图 5.2,class Circle private int radius; Circle(int r) setRadius(r); public void setRadius(int r) radius=r; public int getRadius() return radius; public double area() return 3.14159*radius*radius; public String toString() return 圆半径: +getRadius()+ 圆面积: +area(); public clas

12、s O1 public static void main(String args) Circle c=new Circle(10); System.out.println(n+c.toString(); ,方法覆盖时要特别注意: 用来覆盖的子类方法应和被覆盖的父类方法保持相同名称和相同返回值类型,以及相同的参数个数和参数类型。如果被覆盖的方法没有声明抛出异常,子类的覆盖方法可以有不同的抛出异常子句。 有时,可能不需要完全覆盖一个方法,可以部分覆盖一个方法。部分覆盖是在原方法的基础上添加新的功能,即在子类的覆盖方法中添加一条语句: super.原父类方法名,然后加入其他语句。 注意: 不能覆盖父

13、类中的final方法。同样也不能覆盖父类中的static方法,但可以隐藏这类方法。也就是说,在子类中声明的同名静态方法实际上隐藏了父类中的静态方法。此外,非抽象子类必须覆盖父类中的抽象方法。,例5.3 说明this和super的使用,运行结果如图5.3所示。 图 5.3 class Point protected int x, y;,5.1.4 this和super,Point(int a, int b) setPoint(a, b); public void setPoint(int a, int b) x=a; y=b; class Line extends Point protected

14、 int x, y; Line(int a, int b) super(a, b); setLine(a, b); public void setLine(int x, int y) this.x=x+x; this.y=y+y; ,public double length() int x1=super.x, y1=super.y, x2=this.x, y2=this.y; return Math.sqrt(x2-x1) * (x2-x1) + (y2-y1) * (y2-y1); public String toString() return 直线端点: + super.x + , + s

15、uper.y + + x + , + y + 直线长度: + this.length(); public class ThisDemo public static void main(String args) Line line=new Line(50, 50); System.out.println(n+line.toString(); 总结上例,可以概括出this和super 的作用。,(1) this实际代表的是当前类或对象本身。 在一个类中,this表示对当前类的引用,在使用类的成员时隐含着this引用,尽管可以不明确地写出,例如length和toString中对x和y的使用。当一个类

16、被实例化为一个对象时,this就是对象名的另一种表示。通过this可顺利地访问对象,凡在需要使用对象名的地方均可用this代替。例如:,public class Demo extends java.applet.Applet implements ActionListener Button button1=new Button(Add); public void init() add(button1); button1.addActionListener(this); / 等价于button1.addActionListener(Demo); ,(2) super代表着父类。 如果子类的变量隐

17、藏了父类的变量,使用不加引用的变量一定是子类的变量,如果要使用父类的变量,就必须加上super引用。同样道理,如果有方法覆盖的发生,调用父类的方法时也必须加上super引用。,例5.4 在下面两个类中了解super的使用,运行结果如图5.4所示。 class ClassA boolean var; void method() var=true; class BA extends ClassA boolean var; void method() var=false; super.method(); System.out.println(子类变量var为 +var); System.out.pr

18、intln(父类变量var为 +super.var);, public static void main(String args) BA a=new BA(); a.method(); 图 5.4,(3) super() 可用来调用父类的构造方法。 这也是惟一由程序员间接调用类的构造方法的途径,因为Java规定类的构造方法只能由new操作符调用,程序员不能直接调用。同理,this() 也可用来间接调用当前类或对象的构造方法。 类的构造方法是不能继承的,因为构造方法不是类的成员,没有返回值,也不需要修饰符。又由于父类的构造方法和父类同名,在子类中继承父类的构造方法肯定和子类不同名,这样的继承是无

19、意义的。但子类可以使用super()调用父类的构造方法,如在例5.3中:,class Line extends Point protected int x, y; Line(int a, int b) super(a, b); setLine(a, b); 其中super(a, b) 就是在子类中调用父类的构造方法,为父类的成员变量赋初值。 注意: super() 只能出现在子类的构造方法中,而且必须是子类构造方法中的第一条可执行语句。,类的继承发生在多个类之间,而类的多态只发生在同一个类上。在一个类中,可以定义多个同名的方法,只要确定它们的参数个数和类型不同。这种现象称为类的多态。 多态使程

20、序简洁,为程序员带来很大便利。在面向对象编程中,当程序要实现多个相近的功能时,就给相应的方法起一个共同的名字,用不同的参数代表不同的功能。这样,在使用方法时不论传递什么参数,只要能被程序识别就可以得到确定的结果。 类的多态性体现在方法的重载(overload)上,包括成员方法和构造方法的重载。,5.2 类的多态,方法的重载是指对同名方法的重新定义。 例5.5 对不同的数进行排序输出,运行结果见图5.5。 import java.awt.Graphics; import java.applet.Applet; class IntSort public String sort(int a, int

21、 b) if (ab) return a+ +b; else return b+ +a; public String sort(int a, int b, int c) int swap;,5.2.1 成员方法的重载,if (ab) swap=a; a=b; b=swap; if (ac) swap=a; a=c; c=swap; if (bc) swap=b; b=c; c=swap; return a+ +b+ +c; public String sort(int arr) ,String s= ; int swap; for (int i=0; iarrj+1) swap=arrj; a

22、rrj=arrj+1; arrj+1=swap; for (int i=0; iarr.length; i+) s=s+arri+ ; return s; public class Class2 extends Applet IntSort s=new IntSort();,public void paint(Graphics g) int a=30, b=12, c=40; int arr=34,8,12,67,44,98,52,23,16,16; g.drawString(两个数的排序结果: +s.sort(a,b),30,30); g.drawString(三个数的排序结果: +s.so

23、rt(a,b,c),30,60); g.drawString(数组的排序结果: +s.sort(arr),30,90); 图 5.5,程序可实现对2个数、3个数和数组的排序。在主类Class2中,分别向同一个方法sort传递3种参数,都得到了正确的输出。 IntSort中没有添加成员变量,仅仅提供了3个同名方法: public String sort (int a, int b) public String sort (int a, int b, int c) public String sort (int arr) 它们的区别在于参数的个数和类型的差别,Java解释器在运行这个程序时,可以根

24、据参数的不同来调用不同的方法。,这种多态性使类能够向外提供一个较为一致的接口,对程序员来说,不必关心同名方法内部的细节差别,只要掌握它们在使用时要求什么参数就可以了。 应该注意到,程序中调用了IntSort类的构造方法,但这个构造方法并没有在IntSort中出现,它是怎么来的呢? 每一个类都有一个默认的构造方法,这就是和类同名的无参构造方法。它实际上是父类的构造方法,创建子类时由父类自动提供。因此,每个类的对象都可以使用这种方式来初始化对象。如同为变量声明数据类型一样,可为对象声明类的类型。如果在初始化对象时需要对象具有更多的特性,可重载构造方法。,重载构造方法的目的是提供多种初始化对象的能力

25、,使程序员可以根据实际需要选用合适的构造方法来初始化对象。,5.2.2 构造方法的重载,例5.6 构造方法的重载示例,运行结果如图5.6所示。 class RunDemo private String userName, password; RunDemo() System.out.println(All is null!); RunDemo(String name) userName=name; RunDemo(String name, String pwd) this(name); password=pwd; check(); void check() String s=null;,if

26、(userName!=null) s=用户名: +userName; else s=用户名不能为空!; if (password!=ThisWord) s=s+ 口令无效!; else s=s+ 口令: *; System.out.println(s); public class D1 public static void main(String args) new RunDemo(); new RunDemo(Bill); new RunDemo(null,Bill); new RunDemo(Bill,ThisWord); ,图 5.6 重载构造方法的执行由类根据实际参数的个数、类型和顺序

27、确定,为程序员提供了较大的灵活性。,5-1 什么是类的继承性?子类和父类有什么关系? 5-2 什么是类的多态性? 5-3 何为隐藏、覆盖、重载? 5-4 this和super类有什么作用? 5-5 什么是构造方法? 5-6 构造方法有何特点和作用?,习题,5-7 分析下面这段程序,指出父类、子类以及它们的成员,成员的作用是什么? class Point int x, y; Point(int a, int b) setPoint(a,b); public void setPoint(int a, int b) x=a; y=b; class Circle extends Point int r

28、adius; Circle(int a, int b, int r) super(a,b); setRadius(r); public void setRadius(int r) radius=r; public double area() return 3.14159*radius*radius; ,5-8 给出下面的不完整的类代码: class Person String name, department; int age; public Person(String n) name = n; public Person(String n, int a) name = n; age = a;

29、 public Person(String n, String d, int a) _ department = d; 下面的哪些表达式可以加到构造方法中的“_”处?(C) A. Person(n,a)。 B. this(Person(n,a)。 C. this(n,a)。 D. this(name,age)。,5-9 阅读下面代码: public class Parent public int addValue( int a, int b) int s; s = a+b; return s; class Child extends Parent 下面哪些方法可以加入类Child中?为什么?(

30、BC) A. int addValue( int a, int b )/做某事情 B. public void addValue ()/做某事情 C. public int addValue( int a )/ /做某事情 D. public int addValue( int a, int b )throws MyException /做某事情 (参考方法重载的内容),5-10 给出下面的代码: class Person String name,department; public void printValue() System.out.println(name is +name); Sy

31、stem.out.println(department is +department); public class Teacher extends Person int salary; public void printValue() _ System.out.println(salary is +salary); ,下面的哪些表达式可以加入到Teacher类的 printValue()方法中?为什么?(D) A. printValue()。 B. this.printValue()。 C. person.printValue()。 D. super.printValue()。 5-11 创建一个Fraction类执行分数运算。要求如下: (1) 用整型数表示类的private成员变量(f1和f2)。 (2) 提供构造方法,将分子存入f1,分母存入f2。 (3) 提供两个分数相加的运算方法,结果分别存入f1和f2。 (4) 提供两个分数相减的运算方法,结果分别存入f1和f2。,(5) 提供两个分数相乘的运算方法,结果分别存入f1和f2。 (6) 提供两个分数相除的运算方法,结果分别存入f1和f2。 (7) 以a/b的形式打印Fraction数。 (8) 以浮点数的形式打印Fraction数。 (9) 编写主控程序运行分数运算。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1