49
第 5 第 第第第第第第第第第 第第第第 : 第第第第第第第第第第第 第第第 第 ,一 第第第第

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

  • Upload
    admon

  • View
    167

  • Download
    8

Embed Size (px)

DESCRIPTION

第 5 章 类的继承性与多态性. 主要任务 : 介绍类的继承性和多态性,以及一些 相关问题。. 本章主要内容. 1. 类的继承 2. 类的多态. 5.1 类的继承. 什么是类的继承? 新类可从现有的类中产生,将保留现有类的状态属性和方法并可根据需要加以修改。新类还可添加新的状态属性和方法,这些新增功能允许以统一的风格处理不同类型的数据。这种现象就称为类的继承。. 5.1.1 父类和子类. - PowerPoint PPT Presentation

Citation preview

Page 1: 第 5 章 类的继承性与多态性

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

主要任务 :

介绍类的继承性和多态性,以及一些 相关问题。

Page 2: 第 5 章 类的继承性与多态性

本章主要内容

1.类的继承

2.类的多态

Page 3: 第 5 章 类的继承性与多态性

5.1 类的继承什么是类的继承?新类可从现有的类中产生,将保留现

有类的状态属性和方法并可根据需要加以修改。新类还可添加新的状态属性和方法,这些新增功能允许以统一的风格处理不同类型的数据。这种现象就称为类的继承。

Page 4: 第 5 章 类的继承性与多态性

5.1.1 父类和子类当建立一个新类时,不必写出全部成

员变量和成员方法。只要简单地声明这个类是从一个已定义的类继承下来的,就可以引用被继承类的全部成员。被继承的类称为父类或超类( superclass ),这个新类称为子类。

Page 5: 第 5 章 类的继承性与多态性

在类的声明语句中加入 extends 关键字和指定的类名即可实现类的继承,例如:

public class MyApplet extends java.applet.Applet public class MyApplication extends Frame public class MyApp1 extends Object public class MyApp2

第一条语句声明子类 MyApplet 的父类是 Applet ,并指明 Applet 的层次结构;第二条语句声明子类 MyApplication 的父类是 Frame ;第三条语句声明子类 MyApp1 的父类是 Object ,但编程中通常会省略extends Object 子句;第四条语句在字面上没有 extends ,但实际上等价于 public class MyApp2 extends Object 。

Page 6: 第 5 章 类的继承性与多态性

类的继承的模拟图

Page 7: 第 5 章 类的继承性与多态性

图反映了什么?图 5.1 反映了 Java 类的层次结构。最顶端

的类是 Object ,它在 java.lang 中定义,是所有类的始祖。一个类可以有多个子类,也可以没有子类,但它必定有一个父类( Object 除外)。

子类不能继承父类中的 private 成员,除此之外,其它所有的成员都可以通过继承变为子类的成员。另一方面,对继承的理解应该扩展到整个父类的分支,也就是说,子类继承的成员实际上是整个父系的所有成员。例如, toString 这个方法是在 Object 中声明的,被层层继承了下来,用于输出当前对象的基本信息。

Page 8: 第 5 章 类的继承性与多态性

结论:子类只能有一个父类。如果省略了 ext

ends ,子类的父类是 Object 。子类继承了父类和祖先的成员,可以使用这些成员。在需要的时候,子类可以添加新的成员变量和方法,也可以隐藏父类的成员变量或覆盖父类的成员方法。

Page 9: 第 5 章 类的继承性与多态性

5.1.2 成员变量的继承和隐藏

1 .成员变量的继承

2 .成员变量的隐藏

Page 10: 第 5 章 类的继承性与多态性

例 5.1 下面的三个程序说明从点 Point 类扩展到线 Line 类和圆 Circle 类的方法,这是三个公共类,不能放在同一个文件中。它们都没有输出语句,如果运行看不到什么结果。

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;} public int getY() {return y;}}

Page 11: 第 5 章 类的继承性与多态性

public class Line extends Point { protected int x, y, endX, endY; Line(int x1, int y1, int x2, int y2) {setLine(x

1, y1, x2, y2);} public void setLine(int x1, int y1, int x2, in

t y2) { x=x1; y=y1; endX=x2; endY=y2; }

Page 12: 第 5 章 类的继承性与多态性

public int getX() {return x ;} public int getY() {return y ;} public int getEndX() {return endX;} public int getEndY() {return endY;} public double length() { return Math.sqrt((endX-x) * (endX-

x) + (endY-y) * (endY-y)); }}

Page 13: 第 5 章 类的继承性与多态性

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 double area() {return 3.14159*radiu

s*radius;}}

Page 14: 第 5 章 类的继承性与多态性

Point 的成员

x, y // 受保护的成员变量,代表点的坐标

Point // 点的构造方法 setPoint // 设定点的坐标值的方法 getX, getY // 返回坐标 x 和 y 的值

的方法

Page 15: 第 5 章 类的继承性与多态性

Line 的成员

x, y, endX, endY // 子类受保护的成员变量,代表线的两个端点坐标

Line // 线的构造方法 setLine // 设定线的两个端点坐标值

的方法 getX, getY // 返回起点坐标 x 和 y 的值的方法 getEndX, getEndY // 返回终点坐标 endX 和 endY 的

值的方法 length // 返回线的长度的方法 x, y // 继承父类的受保护成员变

量,但被子类隐藏 setPoint // 继承父类的方法 getX, getY // 继承父类的方法,但被子类覆盖

Page 16: 第 5 章 类的继承性与多态性

Circle 的成员

radius // 子类受保护的成员变量,代表圆的半径

Circle // 圆的构造方法 setRadius // 设定半径值的方法 getRadius // 返回半径值的方法 area // 返回圆面积的方法 x, y // 继承父类的受保护成员变量 setPoint // 继承父类的方法 getX, getY// 继承父类的方法

Page 17: 第 5 章 类的继承性与多态性

2 .成员变量的隐藏所谓隐藏是指子类重新定义了父类中的同名

变量,如子类 Line 重新定义了 x 为 x1 , y为 y1 ,隐藏了父类 Point 中的两个成员变量x 和 y 。子类执行自己的方法时,操作的是子类的变量,子类执行父类的方法时,操作的是父类的变量。在子类中要特别注意成员变量的命名,防止无意中隐藏了父类的关键成员变量,这有可能给你的程序带来麻烦。

Line 还覆盖了 Point 的两个方法 getX 和 getY 。

Page 18: 第 5 章 类的继承性与多态性

5.1.3 成员方法的覆盖已知通过继承子类可以继承父类中所有可以

被子类访问的成员方法,但如果子类的方法与父类方法同名,则不能继承,此时称子类的方法覆盖了父类的那个方法,简称为方法覆盖。方法的覆盖( override ),为子类提供了修改父类成员方法的能力。例如,子类可以修改层层继承下来的 toString 方法,让它输出一些更有用的信息。下面的例子显示了在子类 Circle 中添加 toString 方法,用来返回圆半径和圆面积信息。

Page 19: 第 5 章 类的继承性与多态性

例 5.2 对 Object 的 toString 方法的覆盖。结果如图所示。

Page 20: 第 5 章 类的继承性与多态性

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*radiu

s;} public String toString() { return " 圆半径: "+getRadius()+" 圆面积: "+ar

ea(); }}

Page 21: 第 5 章 类的继承性与多态性

public class O1 { public static void main(String args[]) { Circle c=new Circle(10); System.out.println("\n"+c.toString()); }}程序中改写了上一节介绍的 Circle ,添加了 toStrin

g 方法并修改了它的返回值。由于 toString 和继承下来的方法名相同、返回值类型相同,因此就覆盖了父类中的 toString 方法。而父类 Point 中的 toString 方法尽管没有显示出来,它仍然存在,它是从Object 中继承下来的。

Page 22: 第 5 章 类的继承性与多态性

方法覆盖时要特别注意:用来覆盖的子类方法应和被覆盖的父

类方法保持同名、同返回值类型,以及相同的参数个数和参数类型。如果被覆盖的方法没有声明抛出异常,子类的覆盖方法可以有不同的抛出异常子句。

有时,可能不需要完全覆盖一个方法,可以部分覆盖一个方法。部分覆盖是在原方法的基础上添加新的功能,即在子类的覆盖方法中添加一条语句: super.原父类方法名,然后加入其它语句。

Page 23: 第 5 章 类的继承性与多态性

5.1.4 this 和 super例 5.3 this 和 super 的使用。运行结

果如图所示。

Page 24: 第 5 章 类的继承性与多态性

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;

}

}

Page 25: 第 5 章 类的继承性与多态性

class Line extends Point { protected 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; }

Page 26: 第 5 章 类的继承性与多态性

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 + "," + super.y +

"] [" + x + "," + y + "] 直线长度: " + this.length(); }}

Page 27: 第 5 章 类的继承性与多态性

public class ThisDemo { public static void main(String args[])

{ Line line=new Line(50, 50); System.out.println("\n"+line.toStrin

g()); }}

Page 28: 第 5 章 类的继承性与多态性

this 和 super 的作用: ( 1 ) this 实际代表的是当前类或对象

本身。在一个类中, this 表示对当前类的引

用,在使用类的成员时隐含着 this 引用,尽管可以不明确地写出,例如 length 和 toString 中对 x 和 y 的使用。当一个类被实例化为一个对象时, this就是对象名的另一种表示。通过 this可顺利地访问对象,凡在需要使用对象名的地方均可用 this 代替。

Page 29: 第 5 章 类的继承性与多态性

( 2 ) super 代表着父类

如果子类的变量隐藏了父类的变量,使用不加引用的变量一定是子类的变量,如果使用父类的变量,就必须加上 super 引用。同样道理,如果有方法覆盖的发生,调用父类的方法时也必须加上super 引用。

Page 30: 第 5 章 类的继承性与多态性

例 5.4 了解下面两个类中 super 的使用。运行结果如图所示。

Page 31: 第 5 章 类的继承性与多态性

( 3 ) super() 可用来调用父类的构造方法。

这也是唯一由程序员间接调用类的构造方法的途径,因为 Java规定类的构造方法只能由 new 操作符调用,程序员不能直接调用。同理, this() 也可用来间接调用当前类或对象的构造方法。

类的构造方法是不能继承的,因为构造方法不是类的成员,没有返回值,也不需要修饰符。又由于父类的构造方法和父类同名,在子类中继承父类的构造方法肯定和子类不同名,这样的继承是无意义的。

Page 32: 第 5 章 类的继承性与多态性

5.2 类的多态类的继承发生在多个类之间,而类的多态只发生在同一个类上。在一个类中,可以定义多个同名的方法,只要确定它们的参数个数和类型不同。这种现象称为类的多态。

多态使程序简洁,为程序员带来很大便利。在 OOP 中,当程序要实现多个相近的功能时,就给相应的方法起一个共同的名字,用不同的参数代表不同的功能。这样,在使用方法时不论传递什么参数,只要能被程序识别就可以得到确定的结果。

类的多态性体现在方法的重载( overload )上,包括成员方法和构造方法的重载。

Page 33: 第 5 章 类的继承性与多态性

5.2.1 成员方法的重载

方法的重载是指对同名方法的不同使用方式。

看下面这个例子。

Page 34: 第 5 章 类的继承性与多态性

例 5.5 对不同的数进行排序输出,运行结果见图。

Page 35: 第 5 章 类的继承性与多态性

import java.awt.Graphics;import java.applet.Applet;

class IntSort { public String sort(int a, int b) { if (a>b) return a+" "+b; else return b+" "+a; }

Page 36: 第 5 章 类的继承性与多态性

public String sort(int a, int b, int c) { int swap; if (a<b) { swap=a; a=b; b=swap; } if (a<c) { swap=a; a=c; c=swap; }

Page 37: 第 5 章 类的继承性与多态性

if (b<c) { swap=b; b=c; c=swap; } return a+" "+b+" "+c; } public String sort(int arr[]) { String s=" "; int swap;

Page 38: 第 5 章 类的继承性与多态性

for (int i=0; i<arr.length; i++) for (int j=0; j<arr.length-1; j++) if (arr[j]>arr[j+1]) { swap=arr[j]; arr[j]=arr[j+1]; arr[j+1]=swap; } for (int i=0; i<arr.length; i++) s=s+arr[i]+" "; return s; }}

Page 39: 第 5 章 类的继承性与多态性

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.sort(a,b,

c),30,60); g.drawString(" 数组的排序结果: "+s.sort(arr),30,

90); }}

Page 40: 第 5 章 类的继承性与多态性

程序中调用了 IntSort 类的构造方法,但这个构造方法

并没有在 IntSort 中出现,它是怎么来的呢? 每一个类都有一个缺省的构造方法,

这就是和类同名的无参构造方法。它实际上是父类的构造方法,创建子类时由父类自动提供。因此,每个类的对象都可以使用这种方式来初始化对象。如同为变量声明数据类型一样,可为对象声明类的类型。如果在初始化对象时需要对象具有更多的特性,可重载构造方法。

Page 41: 第 5 章 类的继承性与多态性

5.2.2 构造方法的重载重载构造方法的目的 :

提供多种初始化对象的能力,使程序员可以根据实际需要选用合适的构造方法来初始化对象。

Page 42: 第 5 章 类的继承性与多态性

例 5.6 构造方法的重载。运行结果如图所示 .

Page 43: 第 5 章 类的继承性与多态性

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(); }

Page 44: 第 5 章 类的继承性与多态性

void check() { String s=null; if (userName!=null) s=" 用户名: "+userName; else s=" 用户名不能为空! "; if (password!="ThisWord") s=s+" 口令无效! "; else s=s+" 口令: ********"; System.out.println(s); }}

Page 45: 第 5 章 类的继承性与多态性

public class D1 {

public static void main(String[] args) {

new RunDemo();

new RunDemo("Bill");

new RunDemo(null,"Bill");

new RunDemo("Bill","ThisWord");

}

}

Page 46: 第 5 章 类的继承性与多态性

习 题

1 .什么是类的继承性?子类和父类有什

么关系?2 .什么是类的多态性?3 .何为隐藏、覆盖、重载?4 . this 和 super 类有什么作用?5 .什么是构造方法? 6 .构造方法有何特点和作用?

Page 47: 第 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 radius; 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*radi

us;} }

Page 48: 第 5 章 类的继承性与多态性

8 .给出下面的代码: class Person {       String name,department;       public void printValue(){          System.out.println("name is "+name);          System.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().

Page 49: 第 5 章 类的继承性与多态性

9. 创建一个 Fraction 类执行分数运算。要求如下: ⑴ 用整型数表示类的 private 成员变量: f1 和 f2 。⑵ 提供构造方法,将分子存入 f1 ,分母存入 f2 。⑶ 提供两个分数相加的运算方法,结果分别存入 f1 和

f2 。⑷ 提供两个分数相减的运算方法,结果分别存入 f1 和

f2 。⑸ 提供两个分数相乘的运算方法,结果分别存入 f1 和

f2 。⑹ 提供两个分数相除的运算方法,结果分别存入 f1 和

f2 。⑺ 以 a/b 的形式打印 Fraction 数。⑻ 以浮点数的形式打印 Fraction 数。⑼ 编写主控程序运行分数运算。