收藏 分享(赏)

Java语言程序设计-基础篇-中文ppt-第十一章.ppt

上传人:guanlirenli 文档编号:3206935 上传时间:2018-10-07 格式:PPT 页数:48 大小:464.50KB
下载 相关 举报
Java语言程序设计-基础篇-中文ppt-第十一章.ppt_第1页
第1页 / 共48页
Java语言程序设计-基础篇-中文ppt-第十一章.ppt_第2页
第2页 / 共48页
Java语言程序设计-基础篇-中文ppt-第十一章.ppt_第3页
第3页 / 共48页
Java语言程序设计-基础篇-中文ppt-第十一章.ppt_第4页
第4页 / 共48页
Java语言程序设计-基础篇-中文ppt-第十一章.ppt_第5页
第5页 / 共48页
点击查看更多>>
资源描述

1、1,第11章 继承和多态,2,动 因,假设要定义一个类来对圆、矩形和三角形建模。这些类有很多共同的特性。设计这些类来避免冗余的最好的方式是什么?答案就是使用继承。,3,学习目标,通过继承由父类创建子类 (第11.2节)。 使用关键字super调用父类的构造方法和方法 (第11.3节)。 在子类中覆盖实例方法 (第11.4节)。 区分覆盖和重载的不同 (第11.5节)。 探究Object类中的toString()方法 (第11.6节)。 理解多态性和动态绑定 (第11.7-11.8节)。 描述转换并解释显式向下转换的必要性 (第11.9节)。 探究Object类中的equals方法 (第11.1

2、0节)。 存储、提取和操作ArrayList中的对象 (第11.11节)。 使用ArrayList实现Stack类 (第11.12节)。 使用可见性修饰符protected使父类中的数据和方法可以被子类访问 (第11.13节)。 使用修饰符final防止类的扩展以及方法的覆盖 (第11.14节)。,4,父类和子类,GeometricObject1,Circle4,Rectangle1,TestCircleRectangle,Run,5,父类的构造方法能继承吗?,父类的构造方法不能被继承。 它们被显式或隐式地调用。 使用super关键字显式调用。,构造方法可用来构造一个类的实例。不像属性和方法,

3、父类的构造方法是不能被子类继承的。它们只能从子类的构造方法中用关键字super调用。如果没有显式使用关键字super,那么将自动调用父类的无参构造方法。,6,父类的构造方法总会被调用吗?,构造方法可以调用重载的构造方法或它的父类的构造方法。如果它们都没有被显式调用,那编译器就会自动地将super()作为构造方法的第一条语句。例如:,7,使用super关键字,调用父类的构造方法 调用父类的方法,关键字super是指这个super出现的类的父类。这个关键字super有以下两种途径:,8,警 告,要调用父类的构造方法就必须使用关键字super。在子类中调用父类构造方法的名字会引起一个语法错误。Jav

4、a要求使用关键字super的语句应该是构造方法的第一条语句。,9,构造方法链,public class Faculty extends Employee public static void main(String args) new Faculty();public Faculty() System.out.println(“(4) Facultys no-arg constructor is invoked“); class Employee extends Person public Employee() this(“(2) Invoke Employees overloaded con

5、structor“);System.out.println(“(3) Employees no-arg constructor is invoked“);public Employee(String s) System.out.println(s); class Person public Person() System.out.println(“(1) Persons no-arg constructor is invoked“); ,构造一个类的实例时,将会调用沿着继承链的所有父类的构造方法。这就被称为构造方法链(constructor chaining)。,10,跟踪执行,public

6、class Faculty extends Employee public static void main(String args) new Faculty();public Faculty() System.out.println(“(4) Facultys no-arg constructor is invoked“); class Employee extends Person public Employee() this(“(2) Invoke Employees overloaded constructor“);System.out.println(“(3) Employees n

7、o-arg constructor is invoked“);public Employee(String s) System.out.println(s); class Person public Person() System.out.println(“(1) Persons no-arg constructor is invoked“); ,从main方法开始执行,动 画,11,跟踪执行,public class Faculty extends Employee public static void main(String args) new Faculty();public Facul

8、ty() System.out.println(“(4) Facultys no-arg constructor is invoked“); class Employee extends Person public Employee() this(“(2) Invoke Employees overloaded constructor“);System.out.println(“(3) Employees no-arg constructor is invoked“);public Employee(String s) System.out.println(s); class Person p

9、ublic Person() System.out.println(“(1) Persons no-arg constructor is invoked“); ,2.调用Faculty的 构造方法,动 画,12,跟踪执行,public class Faculty extends Employee public static void main(String args) new Faculty();public Faculty() System.out.println(“(4) Facultys no-arg constructor is invoked“); class Employee ex

10、tends Person public Employee() this(“(2) Invoke Employees overloaded constructor“);System.out.println(“(3) Employees no-arg constructor is invoked“);public Employee(String s) System.out.println(s); class Person public Person() System.out.println(“(1) Persons no-arg constructor is invoked“); ,3. 调用Em

11、ployee的 无参构造方法,动 画,13,跟踪执行,public class Faculty extends Employee public static void main(String args) new Faculty();public Faculty() System.out.println(“(4) Facultys no-arg constructor is invoked“); class Employee extends Person public Employee() this(“(2) Invoke Employees overloaded constructor“);S

12、ystem.out.println(“(3) Employees no-arg constructor is invoked“);public Employee(String s) System.out.println(s); class Person public Person() System.out.println(“(1) Persons no-arg constructor is invoked“); ,4. 调用Employee(String) 构造方法,动 画,14,跟踪执行,public class Faculty extends Employee public static

13、void main(String args) new Faculty();public Faculty() System.out.println(“(4) Facultys no-arg constructor is invoked“); class Employee extends Person public Employee() this(“(2) Invoke Employees overloaded constructor“);System.out.println(“(3) Employees no-arg constructor is invoked“);public Employe

14、e(String s) System.out.println(s); class Person public Person() System.out.println(“(1) Persons no-arg constructor is invoked“); ,5. 调用Person() 构造方法,动 画,15,跟踪执行,public class Faculty extends Employee public static void main(String args) new Faculty();public Faculty() System.out.println(“(4) Facultys

15、no-arg constructor is invoked“); class Employee extends Person public Employee() this(“(2) Invoke Employees overloaded constructor“);System.out.println(“(3) Employees no-arg constructor is invoked“);public Employee(String s) System.out.println(s); class Person public Person() System.out.println(“(1)

16、 Persons no-arg constructor is invoked“); ,6. 执行println,动 画,16,跟踪执行,public class Faculty extends Employee public static void main(String args) new Faculty();public Faculty() System.out.println(“(4) Facultys no-arg constructor is invoked“); class Employee extends Person public Employee() this(“(2) In

17、voke Employees overloaded constructor“);System.out.println(“(3) Employees no-arg constructor is invoked“);public Employee(String s) System.out.println(s); class Person public Person() System.out.println(“(1) Persons no-arg constructor is invoked“); ,7. 执行println,动 画,17,跟踪执行,public class Faculty exte

18、nds Employee public static void main(String args) new Faculty();public Faculty() System.out.println(“(4) Facultys no-arg constructor is invoked“); class Employee extends Person public Employee() this(“(2) Invoke Employees overloaded constructor“);System.out.println(“(3) Employees no-arg constructor

19、is invoked“);public Employee(String s) System.out.println(s); class Person public Person() System.out.println(“(1) Persons no-arg constructor is invoked“); ,8. 执行println,动 画,18,跟踪执行,public class Faculty extends Employee public static void main(String args) new Faculty();public Faculty() System.out.p

20、rintln(“(4) Facultys no-arg constructor is invoked“); class Employee extends Person public Employee() this(“(2) Invoke Employees overloaded constructor“);System.out.println(“(3) Employees no-arg constructor is invoked“);public Employee(String s) System.out.println(s); class Person public Person() Sy

21、stem.out.println(“(1) Persons no-arg constructor is invoked“); ,9. 执行println,动 画,19,父类没有无参构造方法的影响,public class Apple extends Fruit class Fruit public Fruit(String name) System.out.println(“Fruits constructor is invoked“); ,从下面程序中找出错误:,20,声明一个子类,子类从父类那里继承了它的属性和方法,你也可以: 添加新属性 添加新方法 覆盖父类方法,21,调用父类的方法,可

22、以如下改写Circle类中的printCircle()方法:,public void printCircle() System.out.println(“The circle is created “ + super.getDateCreated() + “ and the radius is “ + radius); ,22,覆盖父类的方法,子类从父类中继承方法。有时,子类需要修改父类中定义的方法的实现,这个操作被称作覆盖(method overriding)。,public class Circle extends GeometricObject / Other methods are o

23、mitted/* Override the toString method defined in GeometricObject */public String toString() return super.toString() + “nradius is “ + radius; ,23,注 意,仅当实例方法是可访问时,它才能被覆盖。这样,因为私有方法在它的类本身以外是不能访问的,所以不能覆盖它。如果子类中定义的方法在父类中是私有的,那么这两个方法完全没有关系。,24,注意,与实例方法一样,静态方法也可以被继承。但是,静态方法不能被覆盖。如果父类中定义的静态方法在子类中被重新定义,那么定义在

24、父类中的静态方法将被隐藏。,25,覆盖和重载,26,Object类和它的方法,Java中的每个类都源于java.lang.Object类。如果在定义一个类时没有指定继承性,那么这个类的父类就被默认是Object。,27,Object类中的toString()方法,调用一个对象的toString()会返回一个描述该对象的字符串。它的默认实现会返回一个由该对象所属的类名、at符合()以及一个表示这个对象的数组成的字符串。,Loan loan = new Loan(); System.out.println(loan.toString();,这些代码会显示像Loan15037e5这样的字符串。这个信

25、息不是很有用,或者说没有什么信息量。通常,应该覆盖这个toString方法,这样,它可以返回一个代表该对象的描述性字符串。,28,多态、动态绑定和泛型程序设计,public class PolymorphismDemo public static void main(String args) m(new GraduateStudent();m(new Student();m(new Person();m(new Object();public static void m(Object x) System.out.println(x.toString(); class GraduateStude

26、nt extends Student class Student extends Person public String toString() return “Student“; class Person extends Object public String toString() return “Person“; ,方法m采用一个对象类型的参数。你可以使用任何对象来调用它。,子类的对象可以用在任何需要使用父类对象的地方。这个特征就是通常所说的多态。,当执行方法m(Object x)时,调用参数x的 toString方法。x 可以是GraduateStudent、Student、Perso

27、n或Object的实例。类GraduateStudent、Student、Person和Object都有它自己对toString方法的实现。使用哪个实现是由Java虚拟机在运行时动态决定的。这个功能被称为动态绑定(dynamic binding)。,PolymorphismDemo,Run,29,动态绑定,动态绑定工作机制如下:假设对象o是类C1、 C2、 .、Cn-1 、Cn的实例,其中C1 是C2的子类, C2 是C3的子类, ., Cn-1 是Cn的子类。也就是说,Cn是最通用的类,C1是最特殊的类。在Java中,Cn是Object类。如果对象o调用一个方法p,那么Java虚拟机会依次在

28、类C1、 C2、 .、Cn-1 、 Cn中查找方法p的实现,直到找到为止。一旦找到一个实现,就停止查找并调用这个第一次找到的实现。,30,方法匹配和绑定,匹配方法的签名和绑定方法的实现是两个独立的事情。引用变量的声明类型决定了编译时匹配哪个方法。编译器会在编译时,根据参数类型、参数个数和参数顺序找到匹配的方法。一个方法可能在几个子类中都被实现。Java虚拟机在运行时动态绑定方法的实现,这是由变量的实际类型决定的。参见课后习题10.7和10.9。,31,泛型程序设计,public class PolymorphismDemo public static void main(String args

29、) m(new GraduateStudent();m(new Student();m(new Person();m(new Object();public static void m(Object x) System.out.println(x.toString(); class GraduateStudent extends Student class Student extends Person public String toString() return “Student“; class Person extends Object public String toString() r

30、eturn “Person“; ,多态允许方法可以使用范围更广泛的对象参数。这就是通常所说的泛型程序设计。如果一个方法的参数类型是一个父类(例如:Object),那么可以使用这个父类的子类作为参数(例如:Student或String)。当在一个方法中使用某个对象时(例如:一个student对象或一个String对象),会自动决定调用这些对象中的特定的方法(例如:toString方法)。,32,对象转换,你已经使用过转换运算符把一种基本类型变量转换为另一种基本类型。也可以使用转换把一种类类型的对象转换为继承体系结构中的另一种类类型的对象。在上一节中,语句 m(new Student();将对象n

31、ew Student()赋值给一个Object类型的参数。这条语句等价于Object o = new Student(); / Implicit casting m(o);,语句Object o = new Student()被称为隐式转换(implicit casting),是非法的,因为Student的实例自动地就是Object的实例。,33,为什么转换是重要的?,假设想使用下面的语句把对象引用o赋值给Student类型的变量:Student b = o;在这种情况下,就会发生编译错误。为什么语句Object o = new Student()可以运行,而语句Student b = o就不

32、行呢?原因是Student对象总是Object的实例,但是,Object对象不一定是Student的实例。即使可以看到o实际上是一个Student的对象,但是编译器还没有聪明到懂得这一点。为了告诉编译器o就是一个Student对象,就要使用显式转换(explicit casting)。它的语法与基本类型转换的语法很类似,用圆括弧把目标对象的类型括住,然后放到要转换的对象前面,如下所示:Student b = (Student)o; / Explicit casting,34,将一个父类转换为子类,当把一个父类的实例转换为它的子类变量时,必须使用转换记号“(子类名)”进行显式转换。下面的转换不可

33、能总会成功。 Apple x = (Apple)fruit; Orange x = (Orange)fruit;,35,Instanceof运算符,使用instanceof运算符来检测一个对象是否是一个类的实例:Object myObject = new Circle(); . / Some lines of code /* Perform casting if myObject is an instance of Circle */ if (myObject instanceof Circle) System.out.println(“The circle diameter is “ + (

34、Circle)myObject).getDiameter();. ,36,提 示,为了更好地理解类型转换,可以认为它们类似于水果、苹果、橘子之间的关系,其中水果类Fruit是苹果类Apple和橘子类Orange的父类。苹果是水果,所以,总是可以将Apple的实例安全地赋值给Fruit变量。但是,水果不一定是苹果,所以,必须进行显式转换才能将Fruit 的实例赋值给Apple的变量。,37,实例:演示多态和转换,这个例子创建两个几何对象:一个圆和一个矩形,调用displayGeometricObject方法来显示对象。如果对象是圆,那么方法displayGeometricObject显示对象的区

35、域和半径,如果对象是矩形,则显示对象的区域。,TestPolymorphismCasting,Run,38,equals方法,equals()方法比较两个对象的内容。Object类中equals方法的默认实现如下所示:,public boolean equals(Object obj) return (this = obj); ,例如:Circle类中的equals方法被覆盖。,public boolean equals(Object o) if (o instanceof Circle) return radius = (Circle)o).radius;elsereturn false;

36、,39,注 意,比较运算符= =用来比较两个基本数据类型的值是否相等,或者判断两个对象是否具有相同的引用。如果想让equals方法能够判断两个对象是否具有相同的内容,可以在定义这些对象的类时,覆盖Circle类中的equals方法。运算符= =要比equals方法的功能强大写,因为=运算符可以检测两个引用变量是否指向同一个对象。,40,ArrayList类和Vector类,可以创建一个数组存储对象。但是,一旦创建数组,它的大小就是固定的。Java提供ArrayList类来存储不限定个数的对象。,41,编译警告,从命令行编译这个程序时,会产生警告“unchecked operation.”,忽略

37、这个警告。这个警告可以使用第21章中介绍的泛型类型来消除。,TestArrayList,Run,42,MyStack类,存储对象的栈。,MyStack,43,protected修饰符,Protected修饰符可以用在类中的数据和方法上。公有类中受保护的数据或受保护的方法可以被同一包内的任意类或它的子类访问,即使它的子类在不同包中。 private、default、protected、public,44,可见性总结,45,可见性修饰符,46,子类不能削弱可访问性,子类可以覆盖它的父类的protected方法,并把它的可见性改为public。但是,子类不能削弱父类中定义的方法的可访问性。例如:如果一个方法在父类中定义为public,在子类中也必须定义为public。,47,注 意,修饰符可以用在类和类的成员(数据和方法)上,只有final修饰符还可以用在方法中的局部变量上。方法内的终极局部变量就是常量。,48,final修饰符,final类不能被继承:final class Math . final变量是一个常量:final static double PI = 3.14159; 父类中的final方法不能被子类所覆盖。,

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

当前位置:首页 > 网络科技 > Java

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报